diff options
author | Nathan Straz <nstraz@redhat.com> | 2008-10-20 08:54:08 -0400 |
---|---|---|
committer | Nathan Straz <nstraz@redhat.com> | 2008-10-20 09:05:13 -0400 |
commit | 52c5d049e266416094ce735465c01441649fdfcc (patch) | |
tree | 04e5656bf1a297a6684c1795f3bc043fda1baddb | |
parent | addbac37234057007762f2d60d790d5c68efec18 (diff) | |
download | qarsh-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.c | 25 |
1 files changed, 14 insertions, 11 deletions
@@ -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; } |