From 3ee89ea3fa03f6f98a92d38e68946de29db98f54 Mon Sep 17 00:00:00 2001 From: Nathan Straz Date: Tue, 22 Jul 2014 13:07:19 -0400 Subject: [qarshd] Fix timeout when child exits We ran into an issue where qarsh would wait for 3 seconds after a command ran. This was traced back to the select() in handle_qarsh() being restarted when SIGCHLD was received. I moved the waitpid() to just before the select() and turned off the signal restart. This closes those timing windows and allows qarshd to quickly finish after the child exits. --- qarshd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/qarshd.c b/qarshd.c index 49e763d..5c041c3 100644 --- a/qarshd.c +++ b/qarshd.c @@ -246,8 +246,12 @@ handle_qarsh() int z_in = 0; /* Number of bytes in stdin buffer */ int eof_in = 0; /* Have we seen EOF on stdin yet? */ int nbytes; + struct sigaction chldact; signal(SIGPIPE, SIG_IGN); + chldact.sa_handler = sig_handler; + chldact.sa_flags = 0; /* Make sure SA_RESTART is NOT set so select doesn't timeout on SIGCHLD */ + sigaction(SIGCHLD, &chldact, NULL); qp = make_qp_data_allow(0, QARSHD_BUFSIZE); send_packet(qoutfd, qp); @@ -273,14 +277,16 @@ handle_qarsh() maxfd = childfds[2] > maxfd ? childfds[2] : maxfd; } - nfd = select(maxfd+1, &rfds, &wfds, NULL, &timeout); - + /* Check the child just before we do the select so there's no time + * for the child to exit before the select, causing the select to hang */ if (child_pid && waitpid(child_pid, &child_status, WNOHANG) == child_pid) { rp = make_qp_cmdexit(child_pid, child_status); send_packet(qoutfd, rp); qpfree(rp); child_pid = 0; } + + nfd = select(maxfd+1, &rfds, &wfds, NULL, &timeout); if (nfd < 0) { if (errno == EINTR) { /* signals handled above here */ -- cgit