Skip to content

Invalid coroutine.resume return values #2406

Open

Description

@semyon422

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
                ))
            }
        }
    }
}

Activity

  1. gavin0616 commented on Aug 9, 2025

    @gavin0616
    Contributor

    Lua-nginx module uses a flag is_wrap in ngx_http_lua_coroutine_wrap to indicate that the coroutine is created by coroutine.wrap

    When this flag is set, the first boolean value will not be returned, even when this coroutine is later resumed by coroutine.resume

    if (!ctx->cur_co_ctx->is_wrap) {

    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.

  2. gavin0616 commented on Sep 5, 2025

    @gavin0616
    Contributor

    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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions