changeset 2738:ae81441e23f4

implement "-s signal" option for Unix
author Igor Sysoev <igor@sysoev.ru>
date Tue, 21 Apr 2009 20:25:49 +0000
parents d52cf82d0d77
children 58399dcc410a
files src/core/nginx.c src/core/ngx_cycle.c src/core/ngx_cycle.h src/os/unix/ngx_os.h src/os/unix/ngx_process.c src/os/unix/ngx_process_cycle.h src/os/win32/ngx_os.h src/os/win32/ngx_process_cycle.c src/os/win32/ngx_process_cycle.h
diffstat 9 files changed, 112 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- 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));
--- 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)
 {
--- 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);
--- 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);
--- 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;
+}
--- 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);
--- a/src/os/win32/ngx_os.h
+++ b/src/os/win32/ngx_os.h
@@ -11,6 +11,7 @@
 #include <ngx_config.h>
 #include <ngx_core.h>
 
+
 #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);
--- 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;
 }
 
--- 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);