diff options
author | Nathan Straz <nstraz@redhat.com> | 2014-07-22 13:07:19 -0400 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2014-07-22 13:07:19 -0400 |
commit | 3ee89ea3fa03f6f98a92d38e68946de29db98f54 (patch) | |
tree | d2c130f47fd57265e236294a9c72f544b51bc6ac | |
parent | 10a03d9299757a14525e1177ef34f68b316be1f0 (diff) | |
download | qarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.tar.gz qarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.tar.xz qarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.zip |
[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.
-rw-r--r-- | qarshd.c | 10 |
1 files changed, 8 insertions, 2 deletions
@@ -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 */ |