Mercurial > hg > nginx
comparison src/os/unix/ngx_process_cycle.c @ 3440:88741ec7731a stable-0.7
merge r3294, r3305:
Fix a bug introduced in r2032: After a child process has read a terminate
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.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 01 Feb 2010 15:49:36 +0000 |
parents | 8c76116820f3 |
children | e1409e56ba7c |
comparison
equal
deleted
inserted
replaced
3439:3354dfba9da4 | 3440:88741ec7731a |
---|---|
84 { | 84 { |
85 char *title; | 85 char *title; |
86 u_char *p; | 86 u_char *p; |
87 size_t size; | 87 size_t size; |
88 ngx_int_t i; | 88 ngx_int_t i; |
89 ngx_uint_t n; | 89 ngx_uint_t n, sigio; |
90 sigset_t set; | 90 sigset_t set; |
91 struct itimerval itv; | 91 struct itimerval itv; |
92 ngx_uint_t live; | 92 ngx_uint_t live; |
93 ngx_msec_t delay; | 93 ngx_msec_t delay; |
94 ngx_listening_t *ls; | 94 ngx_listening_t *ls; |
137 NGX_PROCESS_RESPAWN); | 137 NGX_PROCESS_RESPAWN); |
138 ngx_start_cache_manager_processes(cycle, 0); | 138 ngx_start_cache_manager_processes(cycle, 0); |
139 | 139 |
140 ngx_new_binary = 0; | 140 ngx_new_binary = 0; |
141 delay = 0; | 141 delay = 0; |
142 sigio = 0; | |
142 live = 1; | 143 live = 1; |
143 | 144 |
144 for ( ;; ) { | 145 for ( ;; ) { |
145 if (delay) { | 146 if (delay) { |
146 if (ngx_sigalrm) { | 147 if (ngx_sigalrm) { |
148 sigio = 0; | |
147 delay *= 2; | 149 delay *= 2; |
148 ngx_sigalrm = 0; | 150 ngx_sigalrm = 0; |
149 } | 151 } |
150 | 152 |
151 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 153 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
166 | 168 |
167 sigsuspend(&set); | 169 sigsuspend(&set); |
168 | 170 |
169 ngx_time_update(0, 0); | 171 ngx_time_update(0, 0); |
170 | 172 |
171 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up"); | 173 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
174 "wake up, sigio %i", sigio); | |
172 | 175 |
173 if (ngx_reap) { | 176 if (ngx_reap) { |
174 ngx_reap = 0; | 177 ngx_reap = 0; |
175 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); | 178 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); |
176 | 179 |
183 | 186 |
184 if (ngx_terminate) { | 187 if (ngx_terminate) { |
185 if (delay == 0) { | 188 if (delay == 0) { |
186 delay = 50; | 189 delay = 50; |
187 } | 190 } |
191 | |
192 if (sigio) { | |
193 sigio--; | |
194 continue; | |
195 } | |
196 | |
197 sigio = ccf->worker_processes + 2 /* cache processes */; | |
188 | 198 |
189 if (delay > 1000) { | 199 if (delay > 1000) { |
190 ngx_signal_worker_processes(cycle, SIGKILL); | 200 ngx_signal_worker_processes(cycle, SIGKILL); |
191 } else { | 201 } else { |
192 ngx_signal_worker_processes(cycle, | 202 ngx_signal_worker_processes(cycle, |