summaryrefslogtreecommitdiffstats
path: root/qarshd.c
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 /qarshd.c
parent10a03d9299757a14525e1177ef34f68b316be1f0 (diff)
downloadqarsh-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.
Diffstat (limited to 'qarshd.c')
-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 */