Skip to content

Commit e0adfe5

Browse files
committed
bugfix: the UDP and TCP cosockets could not keep track of the current Lua coroutine. now we also explicitly clear the current Lua coroutine context in the main request context to ensure that the I/O scheduler can indeed keep track of the current Lua coroutine itself.
1 parent e49622d commit e0adfe5

File tree

5 files changed

+158
-10
lines changed

5 files changed

+158
-10
lines changed

src/ngx_http_lua_socket_tcp.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,9 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
528528
rctx->timeout = clcf->resolver_timeout;
529529

530530
u->resolved->ctx = rctx;
531+
u->co_ctx = ctx->cur_co_ctx;
532+
533+
coctx->data = u;
531534

532535
saved_top = lua_gettop(L);
533536

@@ -558,14 +561,11 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
558561

559562
/* still resolving */
560563

561-
u->co_ctx = ctx->cur_co_ctx;
562564
u->waiting = 1;
563565
u->prepare_retvals = ngx_http_lua_socket_resolve_retval_handler;
564566

565567
dd("setting data to %p", u);
566568

567-
coctx->data = u;
568-
569569
if (ctx->entered_content_phase) {
570570
r->write_event_handler = ngx_http_lua_content_wev_handler;
571571
}
@@ -600,9 +600,7 @@ ngx_http_lua_socket_resolve_handler(ngx_resolver_ctx_t *ctx)
600600
return;
601601
}
602602

603-
dd("ctx->cur_co_ctx = %p", lctx->cur_co_ctx);
604-
dd("u->co_ctx = %p", u->co_ctx);
605-
603+
lctx->cur_co_ctx = u->co_ctx;
606604
L = lctx->cur_co_ctx->co;
607605

608606
waiting = u->waiting;
@@ -2024,6 +2022,7 @@ ngx_http_lua_socket_handle_success(ngx_http_request_t *r,
20242022
}
20252023

20262024
ctx->resume_handler = ngx_http_lua_socket_tcp_resume;
2025+
ctx->cur_co_ctx = u->co_ctx;
20272026

20282027
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
20292028
"lua tcp socket waking up the current request");
@@ -2060,6 +2059,7 @@ ngx_http_lua_socket_handle_error(ngx_http_request_t *r,
20602059
}
20612060

20622061
ctx->resume_handler = ngx_http_lua_socket_tcp_resume;
2062+
ctx->cur_co_ctx = u->co_ctx;
20632063

20642064
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
20652065
"lua tcp socket waking up the current request");
@@ -3837,10 +3837,16 @@ ngx_http_lua_socket_tcp_resume(ngx_http_request_t *r)
38373837
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
38383838

38393839
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3840-
"lua run subrequests done, resuming lua thread");
3840+
"lua tcp operation done, resuming lua thread");
38413841

38423842
coctx = ctx->cur_co_ctx;
38433843

3844+
#if 0
3845+
ngx_http_lua_probe_info("tcp resume");
3846+
#endif
3847+
3848+
dd("coctx: %p", coctx);
3849+
38443850
u = coctx->data;
38453851

38463852
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,

src/ngx_http_lua_socket_udp.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "ngx_http_lua_util.h"
1010
#include "ngx_http_lua_contentby.h"
1111
#include "ngx_http_lua_output.h"
12+
#include "ngx_http_lua_probe.h"
1213

1314

1415
#define UDP_MAX_DATAGRAM_SIZE 8192
@@ -339,6 +340,7 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L)
339340
rctx->data = u;
340341
rctx->timeout = clcf->resolver_timeout;
341342

343+
u->co_ctx = ctx->cur_co_ctx;
342344
u->resolved->ctx = rctx;
343345

344346
saved_top = lua_gettop(L);
@@ -370,7 +372,6 @@ ngx_http_lua_socket_udp_setpeername(lua_State *L)
370372

371373
/* still resolving */
372374

373-
u->co_ctx = ctx->cur_co_ctx;
374375
u->waiting = 1;
375376
u->prepare_retvals = ngx_http_lua_socket_resolve_retval_handler;
376377

@@ -407,7 +408,11 @@ ngx_http_lua_socket_resolve_handler(ngx_resolver_ctx_t *ctx)
407408
"lua udp socket resolve handler");
408409

409410
lctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
411+
if (lctx == NULL) {
412+
return;
413+
}
410414

415+
lctx->cur_co_ctx = u->co_ctx;
411416
L = lctx->cur_co_ctx->co;
412417

413418
dd("setting socket_ready to 1");
@@ -1122,6 +1127,7 @@ ngx_http_lua_socket_udp_handle_error(ngx_http_request_t *r,
11221127
}
11231128

11241129
ctx->resume_handler = ngx_http_lua_socket_udp_resume;
1130+
ctx->cur_co_ctx = u->co_ctx;
11251131

11261132
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
11271133
"lua udp socket waking up the current request");
@@ -1191,6 +1197,7 @@ ngx_http_lua_socket_udp_handle_success(ngx_http_request_t *r,
11911197
}
11921198

11931199
ctx->resume_handler = ngx_http_lua_socket_udp_resume;
1200+
ctx->cur_co_ctx = u->co_ctx;
11941201

11951202
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
11961203
"lua udp socket waking up the current request");
@@ -1368,10 +1375,14 @@ ngx_http_lua_socket_udp_resume(ngx_http_request_t *r)
13681375
lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
13691376

13701377
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1371-
"lua run subrequests done, resuming lua thread");
1378+
"lua udp operation done, resuming lua thread");
13721379

13731380
coctx = ctx->cur_co_ctx;
13741381

1382+
#if 0
1383+
ngx_http_lua_probe_info("udp resume");
1384+
#endif
1385+
13751386
u = coctx->data;
13761387

13771388
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,

src/ngx_http_lua_util.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,8 @@ ngx_http_lua_run_thread(lua_State *L, ngx_http_request_t *r,
896896
dd("hit! it is the API yield");
897897

898898
lua_settop(ctx->cur_co_ctx->co, 0);
899+
ctx->cur_co_ctx = NULL;
900+
899901
return NGX_AGAIN;
900902

901903
case NGX_HTTP_LUA_USER_CORO_RESUME:

t/058-tcp-socket.t

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,13 @@ close: nil closed
967967
}
968968
--- request
969969
GET /test
970+
971+
--- stap2
972+
M(http-lua-info) {
973+
printf("tcp resume: %p\n", $coctx)
974+
print_ubacktrace()
975+
}
976+
970977
--- response_body
971978
failed to connect: connection refused
972979
--- error_log
@@ -1167,6 +1174,12 @@ function go(port)
11671174
ngx.say("failed to receive a line: ", err, " [", part, "]")
11681175
end
11691176
end
1177+
1178+
--- stap2
1179+
M(http-lua-info) {
1180+
printf("tcp resume\n")
1181+
print_ubacktrace()
1182+
}
11701183
--- request
11711184
GET /t
11721185
--- response_body_like eval

t/087-udp-socket.t

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use Test::Nginx::Socket;
55

66
repeat_each(2);
77

8-
plan tests => repeat_each() * (3 * blocks() + 4);
8+
plan tests => repeat_each() * (3 * blocks() + 6);
99

1010
our $HtmlDir = html_dir;
1111

@@ -252,6 +252,13 @@ function get_udp()
252252

253253
return udp
254254
end
255+
256+
--- stap2
257+
M(http-lua-info) {
258+
printf("tcp resume: %p\n", $coctx)
259+
print_ubacktrace()
260+
}
261+
255262
--- request
256263
GET /main
257264
--- response_body_like: \b500\b
@@ -537,3 +544,112 @@ received: hello world
537544
--- error_log
538545
lua udp socket read timed out
539546

547+
548+
549+
=== TEST 10: access the google DNS server (using IP addr)
550+
--- config
551+
server_tokens off;
552+
location /t {
553+
content_by_lua '
554+
local socket = ngx.socket
555+
-- local socket = require "socket"
556+
557+
local udp = socket.udp()
558+
559+
udp:settimeout(2000) -- 2 sec
560+
561+
local ok, err = udp:setpeername("8.8.8.8", 53)
562+
if not ok then
563+
ngx.say("failed to connect: ", err)
564+
return
565+
end
566+
567+
local req = "\\0}\\1\\0\\0\\1\\0\\0\\0\\0\\0\\0\\3www\\6google\\3com\\0\\0\\1\\0\\1"
568+
569+
-- ngx.print(req)
570+
-- do return end
571+
572+
local ok, err = udp:send(req)
573+
if not ok then
574+
ngx.say("failed to send: ", err)
575+
return
576+
end
577+
578+
local data, err = udp:receive()
579+
if not data then
580+
ngx.say("failed to receive data: ", err)
581+
return
582+
end
583+
584+
if string.match(data, "\\3www\\6google\\3com") then
585+
ngx.say("received a good response.")
586+
else
587+
ngx.say("received a bad response: ", #data, " bytes: ", data)
588+
end
589+
';
590+
}
591+
--- request
592+
GET /t
593+
--- response_body
594+
received a good response.
595+
--- no_error_log
596+
[error]
597+
--- log_level: debug
598+
--- error_log
599+
lua udp socket receive buffer size: 8192
600+
601+
602+
603+
=== TEST 11: access the google DNS server (using domain names)
604+
--- config
605+
server_tokens off;
606+
resolver $TEST_NGINX_RESOLVER;
607+
location /t {
608+
content_by_lua '
609+
local socket = ngx.socket
610+
-- local socket = require "socket"
611+
612+
local udp = socket.udp()
613+
614+
udp:settimeout(2000) -- 2 sec
615+
616+
local ok, err = udp:setpeername("google-public-dns-a.google.com", 53)
617+
if not ok then
618+
ngx.say("failed to connect: ", err)
619+
return
620+
end
621+
622+
local req = "\\0}\\1\\0\\0\\1\\0\\0\\0\\0\\0\\0\\3www\\6google\\3com\\0\\0\\1\\0\\1"
623+
624+
-- ngx.print(req)
625+
-- do return end
626+
627+
local ok, err = udp:send(req)
628+
if not ok then
629+
ngx.say("failed to send: ", err)
630+
return
631+
end
632+
633+
local data, err = udp:receive()
634+
if not data then
635+
ngx.say("failed to receive data: ", err)
636+
return
637+
end
638+
639+
if string.match(data, "\\3www\\6google\\3com") then
640+
ngx.say("received a good response.")
641+
else
642+
ngx.say("received a bad response: ", #data, " bytes: ", data)
643+
end
644+
';
645+
}
646+
--- request
647+
GET /t
648+
--- response_body
649+
received a good response.
650+
--- no_error_log
651+
[error]
652+
--- log_level: debug
653+
--- error_log
654+
lua udp socket receive buffer size: 8192
655+

0 commit comments

Comments
 (0)