Skip to content

Commit acd5364

Browse files
bugfix: nginx crash when resolve an not exist domain in thread create by ngx.thread.spawn.(openresty#1931)
FIX openresty#1915 The resolve ctxes were dded to a link list. function ngx_resolver_process_a iterate through the link list when got the DNS reply. When processing the first resolve ctx, all the three ctxes were freed. So when ngx_resolver_process_a continues to process the second ctx, it will free the ctx again. Co-authored-by: doujiang24 <doujiang24@gmail.com>
1 parent c4ca520 commit acd5364

File tree

4 files changed

+202
-17
lines changed

4 files changed

+202
-17
lines changed

src/ngx_http_lua_socket_tcp.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ static void ngx_http_lua_socket_free_pool(ngx_log_t *log,
147147
static int ngx_http_lua_socket_shutdown_pool(lua_State *L);
148148
static void ngx_http_lua_socket_shutdown_pool_helper(
149149
ngx_http_lua_socket_pool_t *spool);
150-
static void
151-
ngx_http_lua_socket_empty_resolve_handler(ngx_resolver_ctx_t *ctx);
152150
static int ngx_http_lua_socket_prepare_error_retvals(ngx_http_request_t *r,
153151
ngx_http_lua_socket_tcp_upstream_t *u, lua_State *L, ngx_uint_t ft_type);
154152
#if (NGX_HTTP_SSL)
@@ -1151,13 +1149,6 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
11511149
}
11521150

11531151

1154-
static void
1155-
ngx_http_lua_socket_empty_resolve_handler(ngx_resolver_ctx_t *ctx)
1156-
{
1157-
/* do nothing */
1158-
}
1159-
1160-
11611152
static void
11621153
ngx_http_lua_socket_resolve_handler(ngx_resolver_ctx_t *ctx)
11631154
{
@@ -6084,10 +6075,8 @@ ngx_http_lua_tcp_resolve_cleanup(void *data)
60846075
return;
60856076
}
60866077

6087-
/* just to be safer */
6088-
rctx->handler = ngx_http_lua_socket_empty_resolve_handler;
6089-
6090-
ngx_resolve_name_done(rctx);
6078+
/* postpone free the rctx in the handler */
6079+
rctx->handler = ngx_resolve_name_done;
60916080
}
60926081

60936082

src/ngx_http_lua_socket_udp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,8 @@ ngx_http_lua_udp_resolve_cleanup(void *data)
15841584
return;
15851585
}
15861586

1587-
ngx_resolve_name_done(rctx);
1587+
/* postpone free the rctx in the handler */
1588+
rctx->handler = ngx_resolve_name_done;
15881589
}
15891590

15901591

t/014-bugs.t

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ log_level('debug');
88

99
repeat_each(3);
1010

11-
plan tests => repeat_each() * (blocks() * 2 + 30);
11+
plan tests => repeat_each() * (blocks() * 2 + 32);
1212

1313
our $HtmlDir = html_dir;
1414
#warn $html_dir;
@@ -1019,3 +1019,199 @@ write timer set: 1
10191019
--- no_error_log
10201020
[error]
10211021
[alert]
1022+
1023+
1024+
1025+
=== TEST 42: tcp: nginx crash when resolve an not exist domain in ngx.thread.spawn
1026+
https://github.com/openresty/lua-nginx-module/issues/1915
1027+
--- config
1028+
resolver $TEST_NGINX_RESOLVER ipv6=off;
1029+
location = /t {
1030+
content_by_lua_block {
1031+
local function tcp(host, port)
1032+
local sock = ngx.socket.tcp()
1033+
local ok,err = sock:connect(host, port)
1034+
if not ok then
1035+
ngx.log(ngx.WARN, "failed: ", err)
1036+
sock:close()
1037+
return false
1038+
end
1039+
1040+
sock:close()
1041+
return true
1042+
end
1043+
1044+
local host = "www.notexistdomain.com"
1045+
local port = 80
1046+
1047+
local threads = {}
1048+
for i = 1, 3 do
1049+
threads[i] = ngx.thread.spawn(tcp, host, port)
1050+
end
1051+
1052+
local ok, res = ngx.thread.wait(threads[1],threads[2],threads[3])
1053+
if not ok then
1054+
ngx.say("failed to wait thread")
1055+
return
1056+
end
1057+
1058+
ngx.say("res: ", res)
1059+
1060+
for i = 1, 3 do
1061+
ngx.thread.kill(threads[i])
1062+
end
1063+
}
1064+
}
1065+
1066+
--- request
1067+
GET /t
1068+
--- response_body
1069+
res: false
1070+
--- error_log
1071+
www.notexistdomain.com could not be resolved
1072+
1073+
1074+
1075+
=== TEST 43: domain exists with tcp socket
1076+
https://github.com/openresty/lua-nginx-module/issues/1915
1077+
--- config
1078+
resolver $TEST_NGINX_RESOLVER ipv6=off;
1079+
location = /t {
1080+
content_by_lua_block {
1081+
local function tcp(host, port)
1082+
local sock = ngx.socket.tcp()
1083+
local ok,err = sock:connect(host, port)
1084+
if not ok then
1085+
ngx.log(ngx.WARN, "failed: ", err)
1086+
sock:close()
1087+
return false
1088+
end
1089+
1090+
sock:close()
1091+
return true
1092+
end
1093+
1094+
local host = "www.openresty.org"
1095+
local port = 80
1096+
1097+
local threads = {}
1098+
for i = 1, 3 do
1099+
threads[i] = ngx.thread.spawn(tcp, host, port)
1100+
end
1101+
1102+
local ok, res = ngx.thread.wait(threads[1],threads[2],threads[3])
1103+
if not ok then
1104+
ngx.say("failed to wait thread")
1105+
return
1106+
end
1107+
1108+
ngx.say("res: ", res)
1109+
1110+
for i = 1, 3 do
1111+
ngx.thread.kill(threads[i])
1112+
end
1113+
}
1114+
}
1115+
1116+
--- request
1117+
GET /t
1118+
--- response_body
1119+
res: true
1120+
1121+
1122+
1123+
=== TEST 44: domain exists with udp socket
1124+
https://github.com/openresty/lua-nginx-module/issues/1915
1125+
--- config
1126+
resolver $TEST_NGINX_RESOLVER ipv6=off;
1127+
location = /t {
1128+
content_by_lua_block {
1129+
local function udp(host, port)
1130+
local sock = ngx.socket.udp()
1131+
local ok,err = sock:setpeername(host, port)
1132+
if not ok then
1133+
ngx.log(ngx.WARN, "failed: ", err)
1134+
sock:close()
1135+
return false
1136+
end
1137+
1138+
sock:close()
1139+
return true
1140+
end
1141+
1142+
local host = "www.notexistdomain.com"
1143+
local port = 80
1144+
1145+
local threads = {}
1146+
for i = 1, 3 do
1147+
threads[i] = ngx.thread.spawn(udp, host, port)
1148+
end
1149+
1150+
local ok, res = ngx.thread.wait(threads[1],threads[2],threads[3])
1151+
if not ok then
1152+
ngx.say("failed to wait thread")
1153+
return
1154+
end
1155+
1156+
ngx.say("res: ", res)
1157+
1158+
for i = 1, 3 do
1159+
ngx.thread.kill(threads[i])
1160+
end
1161+
}
1162+
}
1163+
1164+
--- request
1165+
GET /t
1166+
--- response_body
1167+
res: false
1168+
--- error_log
1169+
www.notexistdomain.com could not be resolved
1170+
1171+
1172+
1173+
=== TEST 45: udp: nginx crash when resolve an not exist domain in ngx.thread.spawn
1174+
https://github.com/openresty/lua-nginx-module/issues/1915
1175+
--- config
1176+
resolver $TEST_NGINX_RESOLVER ipv6=off;
1177+
location = /t {
1178+
content_by_lua_block {
1179+
local function udp(host, port)
1180+
local sock = ngx.socket.udp()
1181+
local ok,err = sock:setpeername(host, port)
1182+
if not ok then
1183+
ngx.log(ngx.WARN, "failed: ", err)
1184+
sock:close()
1185+
return false
1186+
end
1187+
1188+
sock:close()
1189+
return true
1190+
end
1191+
1192+
local host = "www.openresty.org"
1193+
local port = 80
1194+
1195+
local threads = {}
1196+
for i = 1, 3 do
1197+
threads[i] = ngx.thread.spawn(udp, host, port)
1198+
end
1199+
1200+
local ok, res = ngx.thread.wait(threads[1],threads[2],threads[3])
1201+
if not ok then
1202+
ngx.say("failed to wait thread")
1203+
return
1204+
end
1205+
1206+
ngx.say("res: ", res)
1207+
1208+
for i = 1, 3 do
1209+
ngx.thread.kill(threads[i])
1210+
end
1211+
}
1212+
}
1213+
1214+
--- request
1215+
GET /t
1216+
--- response_body
1217+
res: true

t/127-uthread-kill.t

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ our $StapScript = $t::StapThread::StapScript;
88

99
repeat_each(2);
1010

11-
plan tests => repeat_each() * (blocks() * 5 + 2);
11+
plan tests => repeat_each() * (blocks() * 5 + 1);
1212

1313
$ENV{TEST_NGINX_RESOLVER} ||= '8.8.8.8';
1414
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= '11211';
@@ -184,7 +184,6 @@ killed
184184
[error]
185185
--- error_log
186186
lua tcp socket abort resolver
187-
resolve name done: -2
188187

189188

190189

0 commit comments

Comments
 (0)