summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Straz <nstraz@redhat.com>2014-07-22 13:07:19 -0400
committerNathan Straz <nstraz@redhat.com>2014-07-22 13:07:19 -0400
commit3ee89ea3fa03f6f98a92d38e68946de29db98f54 (patch)
treed2c130f47fd57265e236294a9c72f544b51bc6ac
parent10a03d9299757a14525e1177ef34f68b316be1f0 (diff)
downloadqarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.zip
qarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.tar.gz
qarsh-3ee89ea3fa03f6f98a92d38e68946de29db98f54.tar.xz
[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.c10
1 files 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 */