Invalid coroutine.resume return values
When I create a coroutine using coroutine.wrap and then resume it, coroutine.resume skips the first "status" value and returns all other values. As docs says it must return the first "status" boolean value. I use openresty from AUR: aur/openresty 1.27.1.1-1
$ curl http://localhost:8080/1
2, nil, 3, nil, false, cannot resume dead coroutine
$ curl http://localhost:8080/2
true, 2, true, 3, false, cannot resume dead coroutine
worker_processes 1;
error_log error.log notice;
pid nginx.pid;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
lua_code_cache off;
location /1 {
content_by_lua_block {
local co
local function f()
co = coroutine.running()
coroutine.yield(1)
coroutine.yield(2)
return 3
end
assert(coroutine.wrap(f)() == 1)
local ok1, ret1 = coroutine.resume(co)
local ok2, ret2 = coroutine.resume(co)
local ok3, ret3 = coroutine.resume(co)
ngx.say(("%s, %s, %s, %s, %s, %s"):format(
ok1, ret1, ok2, ret2, ok3, ret3
))
}
}
location /2 {
content_by_lua_block {
local co
local function f()
co = coroutine.running()
coroutine.yield(1)
coroutine.yield(2)
return 3
end
do
local c = coroutine.create(f)
local ok, v = assert(coroutine.resume(c))
assert(v == 1)
end
local ok1, ret1 = coroutine.resume(co)
local ok2, ret2 = coroutine.resume(co)
local ok3, ret3 = coroutine.resume(co)
ngx.say(("%s, %s, %s, %s, %s, %s"):format(
ok1, ret1, ok2, ret2, ok3, ret3
))
}
}
}
}
Lua-nginx module uses a flag is_wrap in ngx_http_lua_coroutine_wrap to indicate that the coroutine is created by coroutine.wrap
https://github.com/openresty/lua-nginx-module/blob/9600893c310f6865efa7f799b1e6426bfd73b220/src/ngx_http_lua_coroutine.c#L97
When this flag is set, the first boolean value will not be returned, even when this coroutine is later resumed by coroutine.resume
https://github.com/openresty/lua-nginx-module/blob/9600893c310f6865efa7f799b1e6426bfd73b220/src/ngx_http_lua_util.c#L1343
One solution for this issue is always to set is_wrap to false in ngx_http_lua_coroutine_resume, and only set it to true at the end of ngx_http_lua_coroutine_wrap_runner function, but I'm not sure whether this solution would be acceptable to the OpenResty team.
I checked the Lua manual, and it doesn't explicitly state that coroutines created with wrap can be used in resume. Moreover, this approach appears to undermine the encapsulation provided by wrap. It seems the usage above might be more like undefined behavior?