Skip to content

Commit 4a5b3f9

Browse files
committed
unix: delay signal handling until after normal i/o
It was reported that some node.js tests fail on AIX because the exit event sometimes comes before the final stdio output of a child process. Work around that by deferring the signal watcher that is used for process management until after the dispatch of regular i/o watchers. Fixes: #610 PR-URL: #611 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
1 parent 572d315 commit 4a5b3f9

4 files changed

Lines changed: 67 additions & 4 deletions

File tree

src/unix/aix.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
118118
uv__io_t* w;
119119
uint64_t base;
120120
uint64_t diff;
121+
int have_signals;
121122
int nevents;
122123
int count;
123124
int nfds;
@@ -225,6 +226,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
225226
goto update_timeout;
226227
}
227228

229+
have_signals = 0;
228230
nevents = 0;
229231

230232
assert(loop->watchers != NULL);
@@ -255,13 +257,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
255257
continue;
256258
}
257259

258-
w->cb(loop, w, pe->revents);
260+
/* Run signal watchers last. This also affects child process watchers
261+
* because those are implemented in terms of signal watchers.
262+
*/
263+
if (w == &loop->signal_io_watcher)
264+
have_signals = 1;
265+
else
266+
w->cb(loop, w, pe->revents);
267+
259268
nevents++;
260269
}
261270

271+
if (have_signals != 0)
272+
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
273+
262274
loop->watchers[loop->nwatchers] = NULL;
263275
loop->watchers[loop->nwatchers + 1] = NULL;
264276

277+
if (have_signals != 0)
278+
return; /* Event loop should cycle now so don't poll again. */
279+
265280
if (nevents != 0) {
266281
if (nfds == ARRAY_SIZE(events) && --count != 0) {
267282
/* Poll for more events but don't block this time. */

src/unix/kqueue.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
7878
sigset_t set;
7979
uint64_t base;
8080
uint64_t diff;
81+
int have_signals;
8182
int filter;
8283
int fflags;
8384
int count;
@@ -192,6 +193,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
192193
goto update_timeout;
193194
}
194195

196+
have_signals = 0;
195197
nevents = 0;
196198

197199
assert(loop->watchers != NULL);
@@ -265,12 +267,26 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
265267
if (revents == 0)
266268
continue;
267269

268-
w->cb(loop, w, revents);
270+
/* Run signal watchers last. This also affects child process watchers
271+
* because those are implemented in terms of signal watchers.
272+
*/
273+
if (w == &loop->signal_io_watcher)
274+
have_signals = 1;
275+
else
276+
w->cb(loop, w, revents);
277+
269278
nevents++;
270279
}
280+
281+
if (have_signals != 0)
282+
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
283+
271284
loop->watchers[loop->nwatchers] = NULL;
272285
loop->watchers[loop->nwatchers + 1] = NULL;
273286

287+
if (have_signals != 0)
288+
return; /* Event loop should cycle now so don't poll again. */
289+
274290
if (nevents != 0) {
275291
if (nfds == ARRAY_SIZE(events) && --count != 0) {
276292
/* Poll for more events but don't block this time. */

src/unix/linux-core.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
188188
sigset_t sigset;
189189
uint64_t sigmask;
190190
uint64_t base;
191+
int have_signals;
191192
int nevents;
192193
int count;
193194
int nfds;
@@ -315,6 +316,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
315316
goto update_timeout;
316317
}
317318

319+
have_signals = 0;
318320
nevents = 0;
319321

320322
assert(loop->watchers != NULL);
@@ -369,13 +371,27 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
369371
pe->events |= w->pevents & (POLLIN | POLLOUT);
370372

371373
if (pe->events != 0) {
372-
w->cb(loop, w, pe->events);
374+
/* Run signal watchers last. This also affects child process watchers
375+
* because those are implemented in terms of signal watchers.
376+
*/
377+
if (w == &loop->signal_io_watcher)
378+
have_signals = 1;
379+
else
380+
w->cb(loop, w, pe->events);
381+
373382
nevents++;
374383
}
375384
}
385+
386+
if (have_signals != 0)
387+
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
388+
376389
loop->watchers[loop->nwatchers] = NULL;
377390
loop->watchers[loop->nwatchers + 1] = NULL;
378391

392+
if (have_signals != 0)
393+
return; /* Event loop should cycle now so don't poll again. */
394+
379395
if (nevents != 0) {
380396
if (nfds == ARRAY_SIZE(events) && --count != 0) {
381397
/* Poll for more events but don't block this time. */

src/unix/sunos.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
140140
unsigned int nfds;
141141
unsigned int i;
142142
int saved_errno;
143+
int have_signals;
143144
int nevents;
144145
int count;
145146
int err;
@@ -230,6 +231,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
230231
return;
231232
}
232233

234+
have_signals = 0;
233235
nevents = 0;
234236

235237
assert(loop->watchers != NULL);
@@ -252,7 +254,14 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
252254
if (w == NULL)
253255
continue;
254256

255-
w->cb(loop, w, pe->portev_events);
257+
/* Run signal watchers last. This also affects child process watchers
258+
* because those are implemented in terms of signal watchers.
259+
*/
260+
if (w == &loop->signal_io_watcher)
261+
have_signals = 1;
262+
else
263+
w->cb(loop, w, pe->portev_events);
264+
256265
nevents++;
257266

258267
if (w != loop->watchers[fd])
@@ -262,9 +271,16 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
262271
if (w->pevents != 0 && QUEUE_EMPTY(&w->watcher_queue))
263272
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
264273
}
274+
275+
if (have_signals != 0)
276+
loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN);
277+
265278
loop->watchers[loop->nwatchers] = NULL;
266279
loop->watchers[loop->nwatchers + 1] = NULL;
267280

281+
if (have_signals != 0)
282+
return; /* Event loop should cycle now so don't poll again. */
283+
268284
if (nevents != 0) {
269285
if (nfds == ARRAY_SIZE(events) && --count != 0) {
270286
/* Poll for more events but don't block this time. */

0 commit comments

Comments
 (0)