Skip to content

Commit e56dac2

Browse files
authored
bugfix: prevent uthread crash by checking coroutine reference before deletion.
1 parent cd24241 commit e56dac2

File tree

2 files changed

+92
-5
lines changed

2 files changed

+92
-5
lines changed

src/ngx_stream_lua_util.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,8 +1051,10 @@ ngx_stream_lua_run_thread(lua_State *L, ngx_stream_lua_request_t *r,
10511051
return NGX_AGAIN;
10521052
}
10531053

1054-
ngx_stream_lua_del_thread(r, L, ctx, ctx->cur_co_ctx);
1055-
ctx->uthreads--;
1054+
if (ctx->cur_co_ctx->co_ref != LUA_NOREF) {
1055+
ngx_stream_lua_del_thread(r, L, ctx, ctx->cur_co_ctx);
1056+
ctx->uthreads--;
1057+
}
10561058

10571059
if (ctx->uthreads == 0) {
10581060
if (ngx_stream_lua_entry_thread_alive(ctx)) {
@@ -1090,7 +1092,9 @@ ngx_stream_lua_run_thread(lua_State *L, ngx_stream_lua_request_t *r,
10901092
lua_xmove(ctx->cur_co_ctx->co, next_co, nrets);
10911093
}
10921094

1093-
if (ctx->cur_co_ctx->is_uthread) {
1095+
if (ctx->cur_co_ctx->is_uthread
1096+
&& ctx->cur_co_ctx->co_ref != LUA_NOREF)
1097+
{
10941098
ngx_stream_lua_del_thread(r, L, ctx, ctx->cur_co_ctx);
10951099
ctx->uthreads--;
10961100
}
@@ -1201,8 +1205,10 @@ ngx_stream_lua_run_thread(lua_State *L, ngx_stream_lua_request_t *r,
12011205
return NGX_AGAIN;
12021206
}
12031207

1204-
ngx_stream_lua_del_thread(r, L, ctx, ctx->cur_co_ctx);
1205-
ctx->uthreads--;
1208+
if (ctx->cur_co_ctx->co_ref != LUA_NOREF) {
1209+
ngx_stream_lua_del_thread(r, L, ctx, ctx->cur_co_ctx);
1210+
ctx->uthreads--;
1211+
}
12061212

12071213
if (ctx->uthreads == 0) {
12081214
if (ngx_stream_lua_entry_thread_alive(ctx)) {

t/127-uthread-kill.t

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ plan tests => repeat_each() * (blocks() * 5 + 1);
1111

1212
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
1313
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
14+
$ENV{TEST_NGINX_REDIS_PORT} ||= '6379';
1415

1516
#no_shuffle();
1617
no_long_string();
@@ -313,3 +314,83 @@ thread created: zombie
313314
[alert]
314315
stream lua tcp socket abort resolver
315316
--- error_log
317+
318+
319+
320+
=== TEST 7: no phantom uthreads decrement after killing parent uthread
321+
--- stream_server_config
322+
content_by_lua_block {
323+
local redis_port = $TEST_NGINX_REDIS_PORT
324+
local dns_threads = {}
325+
326+
dns_threads[1] = ngx.thread.spawn(function()
327+
local sock = ngx.socket.tcp()
328+
sock:settimeout(2000)
329+
local ok, err = sock:connect("127.0.0.1", redis_port)
330+
if not ok then
331+
return nil, err
332+
end
333+
334+
sock:send("PING\r\n")
335+
local line = sock:receive()
336+
sock:setkeepalive()
337+
return line
338+
end)
339+
340+
dns_threads[2] = ngx.thread.spawn(function()
341+
local child = coroutine.create(function()
342+
local sock = ngx.socket.tcp()
343+
sock:settimeout(2000)
344+
local ok, err = sock:connect("127.0.0.1", redis_port)
345+
if not ok then
346+
return nil, err
347+
end
348+
349+
sock:send("PING\r\n")
350+
local line = sock:receive()
351+
sock:setkeepalive()
352+
return line
353+
end)
354+
355+
local ok, res = coroutine.resume(child)
356+
return res
357+
end)
358+
359+
ngx.thread.wait(dns_threads[1], dns_threads[2])
360+
361+
for _, t in ipairs(dns_threads) do
362+
ngx.thread.kill(t)
363+
end
364+
365+
local probe_threads = {}
366+
for i = 1, 10 do
367+
probe_threads[i] = ngx.thread.spawn(function()
368+
local sock = ngx.socket.tcp()
369+
sock:settimeout(2000)
370+
local ok, err = sock:connect("127.0.0.1", redis_port)
371+
if not ok then
372+
return nil, err
373+
end
374+
375+
sock:send("PING\r\n")
376+
local line = sock:receive()
377+
sock:setkeepalive()
378+
return line
379+
end)
380+
end
381+
382+
local ok_count = 0
383+
for i = 1, #probe_threads do
384+
local ok, res = ngx.thread.wait(probe_threads[i])
385+
if ok and res then
386+
ok_count = ok_count + 1
387+
end
388+
end
389+
390+
ngx.say("ok_count=", ok_count)
391+
}
392+
--- stream_response
393+
ok_count=10
394+
--- no_error_log
395+
[error]
396+
[alert]

0 commit comments

Comments
 (0)