diff options
-rw-r--r-- | cli-chansession.c | 11 | ||||
-rw-r--r-- | common-channel.c | 5 | ||||
-rw-r--r-- | svr-chansession.c | 22 |
3 files changed, 23 insertions, 15 deletions
diff --git a/cli-chansession.c b/cli-chansession.c index fee8a22..0f0d07a 100644 --- a/cli-chansession.c +++ b/cli-chansession.c @@ -64,16 +64,17 @@ static void cli_chansessreq(struct Channel *channel) { type = buf_getstring(ses.payload, NULL); wantreply = buf_getbool(ses.payload); - if (strcmp(type, "exit-status") != 0) { + if (strcmp(type, "exit-status") == 0) { + cli_ses.retval = buf_getint(ses.payload); + TRACE(("got exit-status of '%d'", cli_ses.retval)) + } else if (strcmp(type, "exit-signal") == 0) { + TRACE(("got exit-signal, ignoring it")) + } else { TRACE(("unknown request '%s'", type)) send_msg_channel_failure(channel); goto out; } - /* We'll just trust what they tell us */ - cli_ses.retval = buf_getint(ses.payload); - TRACE(("got exit-status of '%d'", cli_ses.retval)) - out: m_free(type); } diff --git a/common-channel.c b/common-channel.c index d87ea7d..fdaeb24 100644 --- a/common-channel.c +++ b/common-channel.c @@ -313,6 +313,7 @@ static void check_close(struct Channel *channel) { /* And if we can't receive any more data from them either, close up */ if (!channel->sent_close && channel->readfd == FD_CLOSED + && (ERRFD_IS_WRITE(channel) || channel->errfd == FD_CLOSED) && !write_pending(channel)) { TRACE(("sending close, readfd is closed")) send_msg_channel_close(channel); @@ -624,8 +625,8 @@ static void send_msg_channel_data(struct Channel *channel, int isextended) { close_chan_fd(channel, fd, SHUT_RD); } ses.writepayload->len = ses.writepayload->pos = 0; - TRACE(("leave send_msg_channel_data: len %d read err or EOF for fd %d", - len, channel->index)); + TRACE(("leave send_msg_channel_data: len %d read err %d or EOF for fd %d", + len, errno, fd)) return; } buf_incrwritepos(ses.writepayload, len); diff --git a/svr-chansession.c b/svr-chansession.c index 23cac85..ae5cb3f 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -67,6 +67,7 @@ extern char** environ; static int sesscheckclose(struct Channel *channel) { struct ChanSess *chansess = (struct ChanSess*)channel->typedata; + TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid)) return chansess->exit.exitpid != -1; } @@ -88,12 +89,13 @@ static void sesssigchild_handler(int UNUSED(dummy)) { TRACE(("enter sigchld handler")) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { + TRACE(("sigchld handler: pid %d", pid)) exit = NULL; /* find the corresponding chansess */ for (i = 0; i < svr_ses.childpidsize; i++) { if (svr_ses.childpids[i].pid == pid) { - + TRACE(("found match session")); exit = &svr_ses.childpids[i].chansess->exit; break; } @@ -102,6 +104,7 @@ static void sesssigchild_handler(int UNUSED(dummy)) { /* If the pid wasn't matched, then we might have hit the race mentioned * above. So we just store the info for the parent to deal with */ if (exit == NULL) { + TRACE(("using lastexit")); exit = &svr_ses.lastexit; } @@ -125,7 +128,8 @@ static void sesssigchild_handler(int UNUSED(dummy)) { while (1) { /* EAGAIN means the pipe's full, so don't need to write anything */ /* isserver is just a random byte to write */ - if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1 || errno == EAGAIN) { + if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1 + || errno == EAGAIN) { break; } if (errno == EINTR) { @@ -142,7 +146,6 @@ static void sesssigchild_handler(int UNUSED(dummy)) { } /* send the exit status or the signal causing termination for a session */ -/* XXX server */ static void send_exitsignalstatus(struct Channel *channel) { struct ChanSess *chansess = (struct ChanSess*)channel->typedata; @@ -181,10 +184,11 @@ static void send_msg_chansess_exitsignal(struct Channel * channel, int i; char* signame = NULL; - dropbear_assert(chansess->exit.exitpid != -1); dropbear_assert(chansess->exit.exitsignal > 0); + TRACE(("send_msg_chansess_exitsignal %d", chansess->exit.exitsignal)) + CHECKCLEARTOWRITE(); /* we check that we can match a signal name, otherwise @@ -294,7 +298,7 @@ static void closechansess(struct Channel *channel) { if (svr_ses.childpids[i].chansess == chansess) { dropbear_assert(svr_ses.childpids[i].pid > 0); TRACE(("closing pid %d", svr_ses.childpids[i].pid)) - TRACE(("exitpid = %d", chansess->exit.exitpid)) + TRACE(("exitpid is %d", chansess->exit.exitpid)) svr_ses.childpids[i].pid = -1; svr_ses.childpids[i].chansess = NULL; } @@ -682,22 +686,24 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) { /* parent */ TRACE(("continue noptycommand: parent")) chansess->pid = pid; + TRACE(("child pid is %d", pid)) addchildpid(chansess, pid); if (svr_ses.lastexit.exitpid != -1) { + TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid)) /* The child probably exited and the signal handler triggered * possibly before we got around to adding the childpid. So we fill - * out it's data manually */ + * out its data manually */ for (i = 0; i < svr_ses.childpidsize; i++) { - if (svr_ses.childpids[i].pid == pid) { + if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) { + TRACE(("found match for lastexitpid")) svr_ses.childpids[i].chansess->exit = svr_ses.lastexit; svr_ses.lastexit.exitpid = -1; } } } - close(infds[FDIN]); close(outfds[FDOUT]); close(errfds[FDOUT]); |