Skip to content

Commit 1b57027

Browse files
committed
synchronized with lua-nginx-module #9a892b8 (coroutine.wrap propagates errors to parent coroutine).
1 parent e51d977 commit 1b57027

File tree

3 files changed

+106
-39
lines changed

3 files changed

+106
-39
lines changed

src/subsys/ngx_subsys_lua_common.h.tt2

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,13 @@ struct ngx_[% subsys %]_lua_co_ctx_s {
591591
the ngx.thread.spawn()
592592
call */
593593
unsigned sem_resume_status:1;
594+
595+
unsigned is_wrap:1; /* set when creating coroutines via
596+
coroutine.wrap */
597+
598+
unsigned propagate_error:1; /* set when propagating an error
599+
from a coroutine to its
600+
parent */
594601
};
595602

596603

src/subsys/ngx_subsys_lua_coroutine.c.tt2

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626

2727
static int ngx_[% subsys %]_lua_coroutine_create(lua_State *L);
28+
static int ngx_[% subsys %]_lua_coroutine_wrap(lua_State *L);
2829
static int ngx_[% subsys %]_lua_coroutine_resume(lua_State *L);
2930
static int ngx_[% subsys %]_lua_coroutine_yield(lua_State *L);
3031
static int ngx_[% subsys %]_lua_coroutine_status(lua_State *L);
@@ -62,6 +63,45 @@ ngx_[% subsys %]_lua_coroutine_create(lua_State *L)
6263
}
6364

6465

66+
static int
67+
ngx_[% subsys %]_lua_coroutine_wrap_runner(lua_State *L)
68+
{
69+
/* retrieve closure and insert it at the bottom of
70+
* the stack for coroutine.resume() */
71+
lua_pushvalue(L, lua_upvalueindex(1));
72+
lua_insert(L, 1);
73+
74+
return ngx_[% subsys %]_lua_coroutine_resume(L);
75+
}
76+
77+
78+
static int
79+
ngx_[% subsys %]_lua_coroutine_wrap(lua_State *L)
80+
{
81+
[% req_type %] *r;
82+
ngx_[% subsys %]_lua_ctx_t *ctx;
83+
ngx_[% subsys %]_lua_co_ctx_t *coctx = NULL;
84+
85+
r = ngx_[% subsys %]_lua_get_req(L);
86+
if (r == NULL) {
87+
return luaL_error(L, "no request found");
88+
}
89+
90+
ctx = ngx_[% req_subsys %]_get_module_ctx(r, ngx_[% subsys %]_lua_module);
91+
if (ctx == NULL) {
92+
return luaL_error(L, "no request ctx found");
93+
}
94+
95+
ngx_[% subsys %]_lua_coroutine_create_helper(L, r, ctx, &coctx);
96+
97+
coctx->is_wrap = 1;
98+
99+
lua_pushcclosure(L, ngx_[% subsys %]_lua_coroutine_wrap_runner, 1);
100+
101+
return 1;
102+
}
103+
104+
65105
int
66106
ngx_[% subsys %]_lua_coroutine_create_helper(lua_State *L,
67107
[% req_type %] *r, ngx_[% subsys %]_lua_ctx_t *ctx,
@@ -270,7 +310,7 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
270310
int rc;
271311

272312
/* new coroutine table */
273-
lua_createtable(L, 0 /* narr */, 14 /* nrec */);
313+
lua_createtable(L, 0 /* narr */, 16 /* nrec */);
274314

275315
/* get old coroutine table */
276316
lua_getglobal(L, "coroutine");
@@ -282,6 +322,9 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
282322
lua_getfield(L, -1, "create");
283323
lua_setfield(L, -3, "_create");
284324

325+
lua_getfield(L, -1, "wrap");
326+
lua_setfield(L, -3, "_wrap");
327+
285328
lua_getfield(L, -1, "resume");
286329
lua_setfield(L, -3, "_resume");
287330

@@ -297,6 +340,9 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
297340
lua_pushcfunction(L, ngx_[% subsys %]_lua_coroutine_create);
298341
lua_setfield(L, -2, "__create");
299342

343+
lua_pushcfunction(L, ngx_[% subsys %]_lua_coroutine_wrap);
344+
lua_setfield(L, -2, "__wrap");
345+
300346
lua_pushcfunction(L, ngx_[% subsys %]_lua_coroutine_resume);
301347
lua_setfield(L, -2, "__resume");
302348

@@ -311,7 +357,7 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
311357
/* inject coroutine APIs */
312358
{
313359
const char buf[] =
314-
"local keys = {'create', 'yield', 'resume', 'status'}\n"
360+
"local keys = {'create', 'yield', 'resume', 'status', 'wrap'}\n"
315361
#ifdef OPENRESTY_LUAJIT
316362
"local get_req = require 'thread.exdata'\n"
317363
#else
@@ -341,24 +387,18 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
341387
"return std(...)\n"
342388
"end\n"
343389
"end\n"
344-
"local create, resume = coroutine.create, coroutine.resume\n"
345-
"coroutine.wrap = function(f)\n"
346-
"local co = create(f)\n"
347-
"return function(...) return select(2, resume(co, ...)) end\n"
348-
"end\n"
349-
"package.loaded.coroutine = coroutine";
350-
390+
"package.loaded.coroutine = coroutine"
351391
#if 0
352392
"debug.sethook(function () collectgarbage() end, 'rl', 1)"
353393
#endif
354394
;
355395

356-
rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "=coroutine.wrap");
396+
rc = luaL_loadbuffer(L, buf, sizeof(buf) - 1, "=coroutine_api");
357397
}
358398

359399
if (rc != 0) {
360400
ngx_log_error(NGX_LOG_ERR, log, 0,
361-
"failed to load Lua code for coroutine.wrap(): %i: %s",
401+
"failed to load Lua code for coroutine_api: %i: %s",
362402
rc, lua_tostring(L, -1));
363403

364404
lua_pop(L, 1);
@@ -368,7 +408,7 @@ ngx_[% subsys %]_lua_inject_coroutine_api(ngx_log_t *log, lua_State *L)
368408
rc = lua_pcall(L, 0, 0, 0);
369409
if (rc != 0) {
370410
ngx_log_error(NGX_LOG_ERR, log, 0,
371-
"failed to run the Lua code for coroutine.wrap(): %i: %s",
411+
"failed to run the Lua code for coroutine_api: %i: %s",
372412
rc, lua_tostring(L, -1));
373413
lua_pop(L, 1);
374414
}

src/subsys/ngx_subsys_lua_util.c.tt2

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,8 +1090,6 @@ ngx_[% subsys %]_lua_run_thread(lua_State *L, [% req_type %] *r,
10901090
/* set Lua VM panic handler */
10911091
lua_atpanic(L, ngx_[% subsys %]_lua_atpanic);
10921092

1093-
dd("ctx = %p", ctx);
1094-
10951093
NGX_LUA_EXCEPTION_TRY {
10961094

10971095
if (ctx->cur_co_ctx->thread_spawn_yielded) {
@@ -1103,19 +1101,15 @@ ngx_[% subsys %]_lua_run_thread(lua_State *L, [% req_type %] *r,
11031101

11041102
for ( ;; ) {
11051103

1106-
dd("calling lua_resume: vm %p, nret %d", ctx->cur_co_ctx->co,
1107-
(int) nrets);
1104+
dd("ctx: %p, co: %p, co status: %d, co is_wrap: %d",
1105+
ctx, ctx->cur_co_ctx->co, ctx->cur_co_ctx->co_status,
1106+
ctx->cur_co_ctx->is_wrap);
11081107

11091108
#if (NGX_PCRE)
11101109
/* XXX: work-around to nginx regex subsystem */
11111110
old_pool = ngx_[% subsys %]_lua_pcre_malloc_init(r->pool);
11121111
#endif
11131112

1114-
/* run code */
1115-
dd("ctx: %p", ctx);
1116-
dd("cur co: %p", ctx->cur_co_ctx->co);
1117-
dd("cur co status: %d", ctx->cur_co_ctx->co_status);
1118-
11191113
orig_coctx = ctx->cur_co_ctx;
11201114

11211115
#ifdef NGX_LUA_USE_ASSERT
@@ -1127,10 +1121,19 @@ ngx_[% subsys %]_lua_run_thread(lua_State *L, [% req_type %] *r,
11271121

11281122
#if DDEBUG
11291123
if (lua_gettop(orig_coctx->co) > 0) {
1130-
dd("top elem: %s", luaL_typename(orig_coctx->co, -1));
1124+
dd("co top elem: %s", luaL_typename(orig_coctx->co, -1));
1125+
}
1126+
1127+
if (orig_coctx->propagate_error) {
1128+
dd("co propagate_error: %d", orig_coctx->propagate_error);
11311129
}
11321130
#endif
11331131

1132+
if (orig_coctx->propagate_error) {
1133+
orig_coctx->propagate_error = 0;
1134+
goto propagate_error;
1135+
}
1136+
11341137
ngx_[% subsys %]_lua_assert(orig_coctx->co_top + nrets
11351138
== lua_gettop(orig_coctx->co));
11361139

@@ -1280,12 +1283,6 @@ ngx_[% subsys %]_lua_run_thread(lua_State *L, [% req_type %] *r,
12801283
next_coctx = ctx->cur_co_ctx->parent_co_ctx;
12811284
next_co = next_coctx->co;
12821285

1283-
/*
1284-
* prepare return values for coroutine.resume
1285-
* (true plus any retvals)
1286-
*/
1287-
lua_pushboolean(next_co, 1);
1288-
12891286
if (nrets) {
12901287
dd("moving %d return values to next co", nrets);
12911288
lua_xmove(ctx->cur_co_ctx->co, next_co, nrets);
@@ -1294,7 +1291,14 @@ ngx_[% subsys %]_lua_run_thread(lua_State *L, [% req_type %] *r,
12941291
#endif
12951292
}
12961293

1297-
nrets++; /* add the true boolean value */
1294+
if (!ctx->cur_co_ctx->is_wrap) {
1295+
/* prepare return values for coroutine.resume
1296+
* (true plus any retvals)
1297+
*/
1298+
lua_pushboolean(next_co, 1);
1299+
lua_insert(next_co, 1);
1300+
nrets++; /* add the true boolean value */
1301+
}
12981302

12991303
ctx->cur_co_ctx = next_coctx;
13001304

@@ -1405,12 +1409,6 @@ user_co_done:
14051409

14061410
next_co = next_coctx->co;
14071411

1408-
/*
1409-
* ended successful, coroutine.resume returns true plus
1410-
* any return values
1411-
*/
1412-
lua_pushboolean(next_co, success);
1413-
14141412
if (nrets) {
14151413
lua_xmove(ctx->cur_co_ctx->co, next_co, nrets);
14161414
}
@@ -1420,7 +1418,15 @@ user_co_done:
14201418
ctx->uthreads--;
14211419
}
14221420

1423-
nrets++;
1421+
if (!ctx->cur_co_ctx->is_wrap) {
1422+
/* ended successfully, coroutine.resume returns true plus
1423+
* any return values
1424+
*/
1425+
lua_pushboolean(next_co, success);
1426+
lua_insert(next_co, 1);
1427+
nrets++;
1428+
}
1429+
14241430
ctx->cur_co_ctx = next_coctx;
14251431

14261432
ngx_[% subsys %]_lua_probe_info("set parent running");
@@ -1476,6 +1482,11 @@ user_co_done:
14761482
ctx->cur_co_ctx);
14771483
trace = lua_tostring(L, -1);
14781484

1485+
propagate_error:
1486+
1487+
ngx_[% subsys %]_lua_assert(err != NULL && msg != NULL
1488+
&& trace != NULL);
1489+
14791490
if (ctx->cur_co_ctx->is_uthread) {
14801491

14811492
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -1573,16 +1584,25 @@ user_co_done:
15731584

15741585
next_coctx->co_status = NGX_[% SUBSYS %]_LUA_CO_RUNNING;
15751586

1587+
ctx->cur_co_ctx = next_coctx;
1588+
1589+
if (orig_coctx->is_wrap) {
1590+
/*
1591+
* coroutine.wrap propagates errors
1592+
* to its parent coroutine
1593+
*/
1594+
next_coctx->propagate_error = 1;
1595+
continue;
1596+
}
1597+
15761598
/*
15771599
* ended with error, coroutine.resume returns false plus
15781600
* err msg
15791601
*/
15801602
lua_pushboolean(next_co, 0);
1581-
lua_xmove(ctx->cur_co_ctx->co, next_co, 1);
1603+
lua_xmove(orig_coctx->co, next_co, 1);
15821604
nrets = 2;
15831605

1584-
ctx->cur_co_ctx = next_coctx;
1585-
15861606
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
15871607
"lua coroutine: %s: %s\n%s", err, msg, trace);
15881608

0 commit comments

Comments
 (0)