7
#include "ngx_http_lua_uthread.h"
8
#include "ngx_http_lua_coroutine.h"
9
#include "ngx_http_lua_util.h"
10
#include "ngx_http_lua_probe.h"
14
#undef ngx_http_lua_probe_info
15
#define ngx_http_lua_probe_info(msg)
19
static int ngx_http_lua_uthread_spawn(lua_State *L);
20
static int ngx_http_lua_uthread_wait(lua_State *L);
24
ngx_http_lua_inject_uthread_api(ngx_log_t *log, lua_State *L)
26
/* new thread table */
29
lua_pushcfunction(L, ngx_http_lua_uthread_spawn);
30
lua_setfield(L, -2, "spawn");
32
lua_pushcfunction(L, ngx_http_lua_uthread_wait);
33
lua_setfield(L, -2, "wait");
35
lua_setfield(L, -2, "thread");
40
ngx_http_lua_uthread_spawn(lua_State *L)
43
ngx_http_request_t *r;
44
ngx_http_lua_ctx_t *ctx;
45
ngx_http_lua_co_ctx_t *coctx = NULL;
49
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
50
lua_rawget(L, LUA_GLOBALSINDEX);
51
r = lua_touserdata(L, -1);
55
return luaL_error(L, "no request found");
58
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
60
return luaL_error(L, "no request ctx found");
63
ngx_http_lua_coroutine_create_helper(L, r, ctx, &coctx);
65
/* anchor the newly created coroutine into the Lua registry */
67
lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
68
lua_rawget(L, LUA_REGISTRYINDEX);
70
coctx->co_ref = luaL_ref(L, -2);
75
lua_xmove(L, coctx->co, n - 1);
78
coctx->is_uthread = 1;
81
coctx->co_status = NGX_HTTP_LUA_CO_RUNNING;
82
ctx->co_op = NGX_HTTP_LUA_USER_THREAD_RESUME;
84
ctx->cur_co_ctx->thread_spawn_yielded = 1;
86
if (ngx_http_lua_post_thread(r, ctx, ctx->cur_co_ctx) != NGX_OK) {
87
return luaL_error(L, "out of memory");
90
coctx->parent_co_ctx = ctx->cur_co_ctx;
91
ctx->cur_co_ctx = coctx;
93
ngx_http_lua_probe_user_thread_spawn(r, L, coctx->co);
95
return lua_yield(L, 1);
100
ngx_http_lua_uthread_wait(lua_State *L)
104
ngx_http_request_t *r;
105
ngx_http_lua_ctx_t *ctx;
106
ngx_http_lua_co_ctx_t *coctx, *sub_coctx;
108
lua_pushlightuserdata(L, &ngx_http_lua_request_key);
109
lua_rawget(L, LUA_GLOBALSINDEX);
110
r = lua_touserdata(L, -1);
114
return luaL_error(L, "no request found");
117
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
119
return luaL_error(L, "no request ctx found");
122
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
123
| NGX_HTTP_LUA_CONTEXT_ACCESS
124
| NGX_HTTP_LUA_CONTEXT_CONTENT);
126
coctx = ctx->cur_co_ctx;
128
nargs = lua_gettop(L);
130
for (i = 1; i <= nargs; i++) {
131
sub_co = lua_tothread(L, i);
133
luaL_argcheck(L, sub_co, i, "lua thread expected");
135
sub_coctx = ngx_http_lua_get_co_ctx(sub_co, ctx);
136
if (sub_coctx == NULL) {
137
return luaL_error(L, "no co ctx found for the ngx.thread "
141
if (!sub_coctx->is_uthread) {
142
return luaL_error(L, "attempt to wait on a coroutine that is "
143
"not a user thread");
146
if (sub_coctx->parent_co_ctx != coctx) {
147
return luaL_error(L, "only the parent coroutine can wait on the "
151
switch (sub_coctx->co_status) {
152
case NGX_HTTP_LUA_CO_ZOMBIE:
154
ngx_http_lua_probe_info("found zombie child");
156
nrets = lua_gettop(sub_coctx->co);
158
dd("child retval count: %d, %s: %s", n,
159
luaL_typename(sub_coctx->co, -1),
160
lua_tostring(sub_coctx->co, -1));
163
lua_xmove(sub_coctx->co, L, nrets);
167
ngx_http_lua_del_thread(r, L, ctx, sub_coctx);
178
ngx_http_lua_probe_user_thread_wait(L, sub_coctx->co);
179
sub_coctx->waited_by_parent = 1;
182
return lua_yield(L, 0);