From 52c5d049e266416094ce735465c01441649fdfcc Mon Sep 17 00:00:00 2001 From: Nathan Straz Date: Mon, 20 Oct 2008 08:54:08 -0400 Subject: [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. --- qarsh.c | 25 ++++++++++++++----------- 1 file 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; } -- cgit