Skip to content

Commit 5a7e66b

Browse files
committed
feature: introduce the lua_sa_restart directive, enabled by default.
This directive sets the SA_RESTART flag on nginx workers signal dispositions.
1 parent e94f2e5 commit 5a7e66b

7 files changed

+254
-0
lines changed

src/ngx_http_lua_common.h

+2
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ struct ngx_http_lua_main_conf_s {
229229

230230
ngx_int_t host_var_index;
231231

232+
ngx_flag_t set_sa_restart;
233+
232234
unsigned requires_header_filter:1;
233235
unsigned requires_body_filter:1;
234236
unsigned requires_capture_filter:1;

src/ngx_http_lua_initworkerby.c

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ ngx_http_lua_init_worker(ngx_cycle_t *cycle)
6767
}
6868
#endif /* NGX_WIN32 */
6969

70+
#if !(NGX_WIN32)
71+
if (lmcf->set_sa_restart) {
72+
ngx_http_lua_set_sa_restart(ngx_cycle->log);
73+
}
74+
#endif
75+
7076
if (lmcf->init_worker_handler == NULL) {
7177
return NGX_OK;
7278
}

src/ngx_http_lua_module.c

+15
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ static ngx_command_t ngx_http_lua_cmds[] = {
104104
0,
105105
NULL },
106106

107+
{ ngx_string("lua_sa_restart"),
108+
NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
109+
ngx_conf_set_flag_slot,
110+
NGX_HTTP_MAIN_CONF_OFFSET,
111+
offsetof(ngx_http_lua_main_conf_t, set_sa_restart),
112+
NULL },
113+
107114
#if (NGX_PCRE)
108115
{ ngx_string("lua_regex_cache_max_entries"),
109116
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
@@ -856,6 +863,8 @@ ngx_http_lua_create_main_conf(ngx_conf_t *cf)
856863
lmcf->postponed_to_rewrite_phase_end = NGX_CONF_UNSET;
857864
lmcf->postponed_to_access_phase_end = NGX_CONF_UNSET;
858865

866+
lmcf->set_sa_restart = NGX_CONF_UNSET;
867+
859868
#if (NGX_HTTP_LUA_HAVE_MALLOC_TRIM)
860869
lmcf->malloc_trim_cycle = NGX_CONF_UNSET_UINT;
861870
#endif
@@ -896,6 +905,12 @@ ngx_http_lua_init_main_conf(ngx_conf_t *cf, void *conf)
896905
lmcf->max_running_timers = 256;
897906
}
898907

908+
#if !(NGX_WIN32)
909+
if (lmcf->set_sa_restart == NGX_CONF_UNSET) {
910+
lmcf->set_sa_restart = 1;
911+
}
912+
#endif
913+
899914
#if (NGX_HTTP_LUA_HAVE_MALLOC_TRIM)
900915
if (lmcf->malloc_trim_cycle == NGX_CONF_UNSET_UINT) {
901916
lmcf->malloc_trim_cycle = 1000; /* number of reqs */

src/ngx_http_lua_util.c

+47
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,25 @@
7070
#endif
7171

7272

73+
#if !(NGX_WIN32)
74+
#define NGX_HTTP_LUA_SA_RESTART_SIGS { \
75+
ngx_signal_value(NGX_RECONFIGURE_SIGNAL), \
76+
ngx_signal_value(NGX_REOPEN_SIGNAL), \
77+
ngx_signal_value(NGX_NOACCEPT_SIGNAL), \
78+
ngx_signal_value(NGX_TERMINATE_SIGNAL), \
79+
ngx_signal_value(NGX_SHUTDOWN_SIGNAL), \
80+
ngx_signal_value(NGX_CHANGEBIN_SIGNAL), \
81+
SIGALRM, \
82+
SIGINT, \
83+
SIGIO, \
84+
SIGCHLD, \
85+
SIGSYS, \
86+
SIGPIPE, \
87+
0 \
88+
};
89+
#endif
90+
91+
7392
char ngx_http_lua_code_cache_key;
7493
char ngx_http_lua_regex_cache_key;
7594
char ngx_http_lua_socket_pool_key;
@@ -4129,4 +4148,32 @@ ngx_http_lua_cleanup_free(ngx_http_request_t *r, ngx_http_cleanup_pt *cleanup)
41294148
}
41304149

41314150

4151+
#if !(NGX_WIN32)
4152+
void
4153+
ngx_http_lua_set_sa_restart(ngx_log_t *log)
4154+
{
4155+
int *signo;
4156+
int sigs[] = NGX_HTTP_LUA_SA_RESTART_SIGS;
4157+
struct sigaction act;
4158+
4159+
for (signo = sigs; *signo != 0; signo++) {
4160+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
4161+
"setting SA_RESTART for signal %d", *signo);
4162+
4163+
if (sigaction(*signo, NULL, &act) != 0) {
4164+
ngx_log_error(NGX_LOG_WARN, log, 0, "failed to get sigaction for "
4165+
"signal %d (%s)", *signo, strerror(errno));
4166+
}
4167+
4168+
act.sa_flags |= SA_RESTART;
4169+
4170+
if (sigaction(*signo, &act, NULL) != 0) {
4171+
ngx_log_error(NGX_LOG_WARN, log, 0, "failed to set sigaction for "
4172+
"signal %d (%s)", *signo, strerror(errno));
4173+
}
4174+
}
4175+
}
4176+
#endif
4177+
4178+
41324179
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

src/ngx_http_lua_util.h

+3
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ ngx_http_cleanup_t *ngx_http_lua_cleanup_add(ngx_http_request_t *r,
243243
void ngx_http_lua_cleanup_free(ngx_http_request_t *r,
244244
ngx_http_cleanup_pt *cleanup);
245245

246+
#if !(NGX_WIN32)
247+
void ngx_http_lua_set_sa_restart(ngx_log_t *log);
248+
#endif
246249

247250
#define ngx_http_lua_check_if_abortable(L, ctx) \
248251
if ((ctx)->no_abort) { \

src/ngx_http_lua_worker.c

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212

1313
#include "ngx_http_lua_worker.h"
14+
#include "ngx_http_lua_util.h"
1415

1516

1617
#define NGX_PROCESS_PRIVILEGED_AGENT 99

t/157-sa-restart.t

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# vim:set ft= ts=4 sw=4 et fdm=marker:
2+
3+
use Test::Nginx::Socket::Lua;
4+
5+
add_block_preprocessor(sub {
6+
my $block = shift;
7+
8+
my $http_config = $block->http_config || '';
9+
10+
$http_config .= <<_EOC_;
11+
init_by_lua_block {
12+
function test_sa_restart()
13+
local signals = {
14+
"HUP",
15+
--"INFO",
16+
--"XCPU",
17+
--"USR1",
18+
--"USR2",
19+
"ALRM",
20+
--"INT",
21+
"IO",
22+
"CHLD",
23+
"WINCH",
24+
}
25+
26+
for _, signame in ipairs(signals) do
27+
local cmd = string.format("kill -s %s %d && sleep 0.01",
28+
signame, ngx.worker.pid())
29+
local err = select(2, io.popen(cmd):read("*a"))
30+
if err then
31+
error("SIG" .. signame .. " caused: " .. err)
32+
end
33+
end
34+
end
35+
}
36+
_EOC_
37+
38+
$block->set_value("http_config", $http_config);
39+
40+
if (!defined $block->config) {
41+
my $config = <<_EOC_;
42+
location /t {
43+
echo ok;
44+
}
45+
_EOC_
46+
47+
$block->set_value("config", $config);
48+
}
49+
50+
if (!defined $block->request) {
51+
$block->set_value("request", "GET /t");
52+
}
53+
54+
if (!defined $block->response_body) {
55+
$block->set_value("ignore_response_body");
56+
}
57+
58+
if (!defined $block->no_error_log) {
59+
$block->set_value("no_error_log", "[error]");
60+
}
61+
});
62+
63+
plan tests => repeat_each() * (blocks() * 2 + 1);
64+
65+
no_long_string();
66+
run_tests();
67+
68+
__DATA__
69+
70+
=== TEST 1: lua_sa_restart default - sets SA_RESTART in init_worker_by_lua*
71+
--- http_config
72+
init_worker_by_lua_block {
73+
test_sa_restart()
74+
}
75+
76+
77+
78+
=== TEST 2: lua_sa_restart off - does not set SA_RESTART
79+
--- http_config
80+
lua_sa_restart off;
81+
82+
init_worker_by_lua_block {
83+
test_sa_restart()
84+
}
85+
--- no_error_log
86+
[crit]
87+
--- error_log
88+
Interrupted system call
89+
90+
91+
92+
=== TEST 3: lua_sa_restart on (default) - sets SA_RESTART if no init_worker_by_lua* phase is defined
93+
--- config
94+
location /t {
95+
content_by_lua_block {
96+
test_sa_restart()
97+
}
98+
}
99+
100+
101+
102+
=== TEST 4: lua_sa_restart on (default) - SA_RESTART is effective in rewrite_by_lua*
103+
--- config
104+
location /t {
105+
rewrite_by_lua_block {
106+
test_sa_restart()
107+
}
108+
109+
echo ok;
110+
}
111+
112+
113+
114+
=== TEST 5: lua_sa_restart on (default) - SA_RESTART is effective in access_by_lua*
115+
--- config
116+
location /t {
117+
access_by_lua_block {
118+
test_sa_restart()
119+
}
120+
121+
echo ok;
122+
}
123+
124+
125+
126+
=== TEST 6: lua_sa_restart on (default) - SA_RESTART is effective in content_by_lua*
127+
--- config
128+
location /t {
129+
content_by_lua_block {
130+
test_sa_restart()
131+
}
132+
}
133+
134+
135+
136+
=== TEST 7: lua_sa_restart on (default) - SA_RESTART is effective in header_filter_by_lua*
137+
--- config
138+
location /t {
139+
echo ok;
140+
141+
header_filter_by_lua_block {
142+
test_sa_restart()
143+
}
144+
}
145+
146+
147+
148+
=== TEST 8: lua_sa_restart on (default) - SA_RESTART is effective in body_filter_by_lua*
149+
--- config
150+
location /t {
151+
echo ok;
152+
153+
body_filter_by_lua_block {
154+
test_sa_restart()
155+
}
156+
}
157+
158+
159+
160+
=== TEST 9: lua_sa_restart on (default) - SA_RESTART is effective in log_by_lua*
161+
--- config
162+
location /t {
163+
echo ok;
164+
165+
log_by_lua_block {
166+
test_sa_restart()
167+
}
168+
}
169+
170+
171+
172+
=== TEST 10: lua_sa_restart on (default) - SA_RESTART is effective in timer phase
173+
--- config
174+
location /t {
175+
echo ok;
176+
177+
log_by_lua_block {
178+
ngx.timer.at(0, test_sa_restart)
179+
}
180+
}

0 commit comments

Comments
 (0)