summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Straz <nstraz@redhat.com>2008-10-20 08:54:08 -0400
committerNathan Straz <nstraz@redhat.com>2008-10-20 09:05:13 -0400
commit52c5d049e266416094ce735465c01441649fdfcc (patch)
tree04e5656bf1a297a6684c1795f3bc043fda1baddb
parentaddbac37234057007762f2d60d790d5c68efec18 (diff)
downloadqarsh-52c5d049e266416094ce735465c01441649fdfcc.tar.gz
qarsh-52c5d049e266416094ce735465c01441649fdfcc.tar.xz
qarsh-52c5d049e266416094ce735465c01441649fdfcc.zip
[qarsh] Fix double-free and command hang
We need to test all exit conditions at once so we fall back into the hbeat code. I was falling into a case when running "reboot -fin &" where the command would exit, but the sockets would not close and we weren't getting to hbeat() to detect the reboot. In another case which I can't completely explain, we were getting a double-free error from glibc in the qpfree() at the end of run_remote_cmd(). Instead of waiting until the very end to read the exit status, save it off as soon as we get the packet and use cmd_exitted to determine if we have an exit code or if something went horribly wrong.
-rw-r--r--qarsh.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/qarsh.c b/qarsh.c
index fce6ad2..31ff36a 100644
--- a/qarsh.c
+++ b/qarsh.c
@@ -292,14 +292,16 @@ run_remote_cmd(char *cmdline)
&pselect_sigmask);
if (nset == 0) {
- if (cmd_finished) {
- /* we don't want to check the heartbeat, just
- * the output sockets */
- if (c_out == 0 && c_err == 0) break;
+ if (cmd_finished && c_out == 0 && c_err == 0) {
+ /* If the command is complete and both output
+ * sockets are closed, we can exit now. We need
+ * to test all conditions at once so if none are
+ * true, we'll still check for heartbeat. */
+ break;
} else if (!hbeat(qarsh_hb)) {
- /* Set our return packet as NULL so we exit
- * with unknown error. */
- qp = NULL;
+ /* If the heartbeat fails, we should exit now.
+ * The hbeat state will take precedence over the
+ * exit status of the command. */
break;
} else {
/* No output to process, the command is
@@ -374,7 +376,10 @@ run_remote_cmd(char *cmdline)
/* dump_qp(qp); */
if (qp && qp->qp_type == QP_CMDEXIT) {
cmd_finished = 1;
- /* break; */
+ rc = qp->qp_cmdexit.qp_status;
+ qpfree(qp);
+ /* Don't break yet, we need to make
+ * sure all output is read. */
}
nset--;
}
@@ -391,12 +396,10 @@ run_remote_cmd(char *cmdline)
fprintf(stderr, "Remote host rebooted\n");
return W_EXITCODE(127, 0);
}
- if (qp == NULL) {
+ if (!cmd_finished) {
fprintf(stderr, "Remote command exited with unknown state\n");
return W_EXITCODE(127, 0);
}
- rc = qp->qp_cmdexit.qp_status;
- qpfree(qp);
return rc;
}