create function t1()
returns setof integer
language pllua
as $$
for i = 1,4 do
server.execute("select * from t1()")
coroutine.yield(i)
end
$$;
select * from t1();
LOG: server process (PID 58621) was terminated by signal 11: Segmentation fault
DETAIL: Failed process was running: select * from t1();
create function t2()
returns setof integer
language pllua
as $$
for i = 1,4 do coroutine.yield(i) end
$$;
select t2(), t2(); -- produces an infinite result
This looks like a design problem stemming from the fact that pllua thinks it can use the luaP_Info, which is shared between the two calls, for state information about the current call (specifically, fi->L as the current thread). It looks like this needs to be redone to put such state info into a structure hung off flinfo (flinfo->fn_extra) as per the standard value-per-call protocol; each call site gets its own flinfo.
(Some existing core pls like plpgsql use fnextra to point to a shared cache entry, but these don't allow value-per-call mode for SETOF, they only do materialize mode which doesn't require keeping state across calls. plpython, which is the only core pl to use value-per-call mode, uses the standard SRF* macros which rely on flinfo->fn_extra.)
This looks like a design problem stemming from the fact that pllua thinks it can use the luaP_Info, which is shared between the two calls, for state information about the current call (specifically, fi->L as the current thread). It looks like this needs to be redone to put such state info into a structure hung off flinfo (flinfo->fn_extra) as per the standard value-per-call protocol; each call site gets its own flinfo.
(Some existing core pls like plpgsql use fnextra to point to a shared cache entry, but these don't allow value-per-call mode for SETOF, they only do materialize mode which doesn't require keeping state across calls. plpython, which is the only core pl to use value-per-call mode, uses the standard SRF* macros which rely on flinfo->fn_extra.)