# HG changeset patch # User Igor Sysoev # Date 1240345549 0 # Node ID ae81441e23f41a743f8d7338efed35d72d1f4729 # Parent d52cf82d0d776c01c86bd3ac59e4c16cfdaaf6f4 implement "-s signal" option for Unix diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -188,9 +188,7 @@ static ngx_uint_t ngx_show_version; static ngx_uint_t ngx_show_configure; static u_char *ngx_conf_file; static u_char *ngx_conf_params; -#if (NGX_WIN32) static char *ngx_signal; -#endif static char **ngx_os_environ; @@ -213,20 +211,16 @@ main(int argc, char *const *argv) if (ngx_show_help) { ngx_log_stderr( - "Usage: nginx [-?hvVt]" -#if (NGX_WIN32) - " [-s signal]" -#endif - " [-c filename] [-g directives]" CRLF CRLF + "Usage: nginx [-?hvVt] [-s signal] [-c filename] " + "[-g directives]" CRLF CRLF "Options:" CRLF " -?,-h : this help" CRLF " -v : show version and exit" CRLF " -V : show version and configure options then exit" CRLF " -t : test configuration and exit" CRLF -#if (NGX_WIN32) - " -s signal : send signal to a master process" CRLF -#endif + " -s signal : send signal to a master process: " + "stop, quit, reopen, reload" CRLF " -c filename : set configuration file (default: " NGX_CONF_PATH ")" CRLF " -g directives : set global directives out of configuration " @@ -337,13 +331,11 @@ main(int argc, char *const *argv) ngx_process = NGX_PROCESS_MASTER; } -#if (NGX_WIN32) - if (ngx_signal) { return ngx_signal_process(cycle, ngx_signal); } -#else +#if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; @@ -685,7 +677,6 @@ ngx_get_options(int argc, char *const *a ngx_log_stderr("the option \"-g\" requires parameter"); return NGX_ERROR; -#if (NGX_WIN32) case 's': if (*p) { ngx_signal = (char *) p; @@ -709,7 +700,6 @@ ngx_get_options(int argc, char *const *a ngx_log_stderr("invalid option: \"-s %s\"", ngx_signal); return NGX_ERROR; -#endif default: ngx_log_stderr("invalid option: \"%c\"", *(p - 1)); diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -569,12 +569,14 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } } - if (ngx_open_listening_sockets(cycle) != NGX_OK) { - goto failed; - } + if (ngx_process != NGX_PROCESS_SIGNALLER) { + if (ngx_open_listening_sockets(cycle) != NGX_OK) { + goto failed; + } - if (!ngx_test_config) { - ngx_configure_listening_socket(cycle); + if (!ngx_test_config) { + ngx_configure_listening_socket(cycle); + } } @@ -986,6 +988,58 @@ ngx_delete_pidfile(ngx_cycle_t *cycle) } +ngx_int_t +ngx_signal_process(ngx_cycle_t *cycle, char *sig) +{ + ssize_t n; + ngx_int_t pid; + ngx_file_t file; + ngx_core_conf_t *ccf; + u_char buf[NGX_INT64_LEN + 2]; + + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started"); + + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + + file.name = ccf->pid; + file.log = cycle->log; + + file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, + NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); + + if (file.fd == NGX_INVALID_FILE) { + ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno, + ngx_open_file_n " \"%s\" failed", file.name.data); + return 1; + } + + n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0); + + if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", file.name.data); + } + + if (n == NGX_ERROR) { + return 1; + } + + while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ } + + pid = ngx_atoi(buf, ++n); + + if (pid == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, + "invalid PID number \"%*s\" in \"%s\"", + n, buf, file.name.data); + return 1; + } + + return ngx_os_signal_process(cycle, sig, pid); + +} + + static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log) { diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -116,6 +116,7 @@ typedef struct { ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle); ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log); void ngx_delete_pidfile(ngx_cycle_t *cycle); +ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig); void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); diff --git a/src/os/unix/ngx_os.h b/src/os/unix/ngx_os.h --- a/src/os/unix/ngx_os.h +++ b/src/os/unix/ngx_os.h @@ -37,6 +37,7 @@ void ngx_os_status(ngx_log_t *log); ngx_int_t ngx_os_specific_init(ngx_log_t *log); void ngx_os_specific_status(ngx_log_t *log); ngx_int_t ngx_daemon(ngx_log_t *log); +ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid); ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size); diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -13,6 +13,7 @@ typedef struct { int signo; char *signame; + char *name; void (*handler)(int signo); } ngx_signal_t; @@ -36,39 +37,45 @@ ngx_process_t ngx_processes[NGX_MAX_P ngx_signal_t signals[] = { { ngx_signal_value(NGX_RECONFIGURE_SIGNAL), "SIG" ngx_value(NGX_RECONFIGURE_SIGNAL), + "reload", ngx_signal_handler }, { ngx_signal_value(NGX_REOPEN_SIGNAL), "SIG" ngx_value(NGX_REOPEN_SIGNAL), + "reopen", ngx_signal_handler }, { ngx_signal_value(NGX_NOACCEPT_SIGNAL), "SIG" ngx_value(NGX_NOACCEPT_SIGNAL), + "", ngx_signal_handler }, { ngx_signal_value(NGX_TERMINATE_SIGNAL), "SIG" ngx_value(NGX_TERMINATE_SIGNAL), + "stop", ngx_signal_handler }, { ngx_signal_value(NGX_SHUTDOWN_SIGNAL), "SIG" ngx_value(NGX_SHUTDOWN_SIGNAL), + "quit", ngx_signal_handler }, { ngx_signal_value(NGX_CHANGEBIN_SIGNAL), "SIG" ngx_value(NGX_CHANGEBIN_SIGNAL), + "", ngx_signal_handler }, - { SIGALRM, "SIGALRM", ngx_signal_handler }, + { SIGALRM, "SIGALRM", "", ngx_signal_handler }, - { SIGINT, "SIGINT", ngx_signal_handler }, + { SIGINT, "SIGINT", "", ngx_signal_handler }, - { SIGIO, "SIGIO", ngx_signal_handler }, + { SIGIO, "SIGIO", "", ngx_signal_handler }, - { SIGCHLD, "SIGCHLD", ngx_signal_handler }, + { SIGCHLD, "SIGCHLD", "", ngx_signal_handler }, - { SIGPIPE, "SIGPIPE, SIG_IGN", SIG_IGN }, + { SIGPIPE, "SIGPIPE, SIG_IGN", "", SIG_IGN }, - { 0, NULL, NULL } + { 0, NULL, "", NULL } }; @@ -540,3 +547,23 @@ ngx_debug_point(void) ngx_abort(); } } + + +ngx_int_t +ngx_os_signal_process(ngx_cycle_t *cycle, char *name, ngx_int_t pid) +{ + ngx_signal_t *sig; + + for (sig = signals; sig->signo != 0; sig++) { + if (ngx_strcmp(name, sig->name) == 0) { + if (kill(pid, sig->signo) != -1) { + return 0; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "kill(%P, %d) failed", pid, sig->signo); + } + } + + return 1; +} diff --git a/src/os/unix/ngx_process_cycle.h b/src/os/unix/ngx_process_cycle.h --- a/src/os/unix/ngx_process_cycle.h +++ b/src/os/unix/ngx_process_cycle.h @@ -19,9 +19,10 @@ #define NGX_CMD_REOPEN 5 -#define NGX_PROCESS_SINGLE 0 -#define NGX_PROCESS_MASTER 1 -#define NGX_PROCESS_WORKER 2 +#define NGX_PROCESS_SINGLE 0 +#define NGX_PROCESS_MASTER 1 +#define NGX_PROCESS_WORKER 2 +#define NGX_PROCESS_SIGNALLER 3 void ngx_master_process_cycle(ngx_cycle_t *cycle); diff --git a/src/os/win32/ngx_os.h b/src/os/win32/ngx_os.h --- a/src/os/win32/ngx_os.h +++ b/src/os/win32/ngx_os.h @@ -11,6 +11,7 @@ #include #include + #define NGX_IO_SENDFILE 1 @@ -32,6 +33,7 @@ typedef struct { ngx_int_t ngx_os_init(ngx_log_t *log); void ngx_os_status(ngx_log_t *log); +ngx_int_t ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid); ssize_t ngx_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); ssize_t ngx_overlapped_wsarecv(ngx_connection_t *c, u_char *buf, size_t size); diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -1006,50 +1006,11 @@ ngx_single_process_cycle(ngx_cycle_t *cy ngx_int_t -ngx_signal_process(ngx_cycle_t *cycle, char *sig) +ngx_os_signal_process(ngx_cycle_t *cycle, char *sig, ngx_int_t pid) { - size_t n; - HANDLE ev; - ngx_int_t rc, pid; - ngx_file_t file; - ngx_core_conf_t *ccf; - u_char buf[NGX_INT64_LEN + 2]; - char evn[NGX_PROCESS_SYNC_NAME]; - - ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started"); - - ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); - - file.name = ccf->pid; - file.log = cycle->log; - - file.fd = ngx_open_file(file.name.data, NGX_FILE_RDONLY, - NGX_FILE_OPEN, NGX_FILE_DEFAULT_ACCESS); - - if (file.fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno, - ngx_open_file_n " \"%s\" failed", file.name.data); - return 1; - } - - rc = 1; - - n = ngx_read_file(&file, buf, NGX_INT64_LEN + 2, 0); - - if (n == NGX_ERROR) { - goto failed; - } - - while (n-- && (buf[n] == CR || buf[n] == LF)) { /* void */ } - - pid = ngx_atoi(buf, ++n); - - if (pid == NGX_ERROR) { - ngx_log_error(NGX_LOG_ERR, cycle->log, 0, - "invalid PID number \"%*s\" in \"%s\"", - n, buf, file.name.data); - goto failed; - } + HANDLE ev; + ngx_int_t rc; + char evn[NGX_PROCESS_SYNC_NAME]; ngx_sprintf((u_char *) evn, "ngx_%s_%ul%Z", sig, pid); @@ -1057,25 +1018,20 @@ ngx_signal_process(ngx_cycle_t *cycle, c if (ev == NULL) { ngx_log_error(NGX_LOG_ERR, cycle->log, ngx_errno, "OpenEvent(\"%s\") failed", evn); - goto failed; + return 1; } if (SetEvent(ev) == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "SetEvent(\"%s\") failed", evn); + rc = 1; + } else { rc = 0; } ngx_close_handle(ev); -failed: - - if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, - ngx_close_file_n " \"%s\" failed", file.name.data); - } - return rc; } diff --git a/src/os/win32/ngx_process_cycle.h b/src/os/win32/ngx_process_cycle.h --- a/src/os/win32/ngx_process_cycle.h +++ b/src/os/win32/ngx_process_cycle.h @@ -20,7 +20,6 @@ void ngx_master_process_cycle(ngx_cycle_t *cycle); void ngx_single_process_cycle(ngx_cycle_t *cycle); -ngx_int_t ngx_signal_process(ngx_cycle_t *cycle, char *sig); void ngx_close_handle(HANDLE h);