]> git.kaiwu.me - nginx.git/commitdiff
Fix a bug introduced in r2032: After a child process has read a terminate
authorIgor Sysoev <igor@sysoev.ru>
Wed, 4 Nov 2009 19:41:08 +0000 (19:41 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Wed, 4 Nov 2009 19:41:08 +0000 (19:41 +0000)
message from a channel, the process tries to read the channel again.
The kernel (at least FreeBSD) may preempt the process and sends a SIGIO
signal to a master process. The master process sends a new terminate message,
the kernel switches again to the the child process, and the child process
reads the messages instead of an EAGAIN error. And this may repeat over
and over. Being that the child process can not exit the cycle and test
the termination flag set by the message handler.

The fix disallow the master process to send a new terminate message on
SIGIO signal reception. It may send the message only on SIGALARM signal.

src/os/unix/ngx_process_cycle.c

index 15a2a8bab63595f395470fa798619d40ca71f025..4b740305462f62180e6b1e03378c9a300db9b742 100644 (file)
@@ -86,7 +86,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
     u_char            *p;
     size_t             size;
     ngx_int_t          i;
-    ngx_uint_t         n;
+    ngx_uint_t         n, sigio;
     sigset_t           set;
     struct itimerval   itv;
     ngx_uint_t         live;
@@ -139,11 +139,13 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
 
     ngx_new_binary = 0;
     delay = 0;
+    sigio = 0;
     live = 1;
 
     for ( ;; ) {
         if (delay) {
             if (ngx_sigalrm) {
+                sigio = 0;
                 delay *= 2;
                 ngx_sigalrm = 0;
             }
@@ -168,7 +170,8 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
 
         ngx_time_update(0, 0);
 
-        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up");
+        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+                       "wake up, sigio %i", sigio);
 
         if (ngx_reap) {
             ngx_reap = 0;
@@ -186,6 +189,13 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
                 delay = 50;
             }
 
+            if (sigio) {
+                sigio--;
+                continue;
+            }
+
+            sigio = ccf->worker_processes + 2 /* cache processes */;
+
             if (delay > 1000) {
                 ngx_signal_worker_processes(cycle, SIGKILL);
             } else {