diff options
Diffstat (limited to 'svr-chansession.c')
-rw-r--r-- | svr-chansession.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/svr-chansession.c b/svr-chansession.c index b6544e6..619a451 100644 --- a/svr-chansession.c +++ b/svr-chansession.c @@ -59,7 +59,6 @@ static void send_msg_chansess_exitstatus(struct Channel * channel, struct ChanSess * chansess); static void send_msg_chansess_exitsignal(struct Channel * channel, struct ChanSess * chansess); -static int sesscheckclose(struct Channel *channel); static void get_termmodes(struct ChanSess *chansess); @@ -68,7 +67,8 @@ extern char** environ; static int sesscheckclose(struct Channel *channel) { struct ChanSess *chansess = (struct ChanSess*)channel->typedata; - return chansess->exit.exitpid >= 0; + TRACE(("sesscheckclose, pid is %d", chansess->exit.exitpid)) + return chansess->exit.exitpid != -1; } /* Handler for childs exiting, store the state for return to the client */ @@ -89,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; } @@ -103,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; } @@ -121,9 +123,18 @@ static void sesssigchild_handler(int UNUSED(dummy)) { /* we use this to determine how pid exited */ exit->exitsignal = -1; } + + /* Make sure that the main select() loop wakes up */ + while (1) { + /* isserver is just a random byte to write. We can't do anything + about an error so should just ignore it */ + if (write(ses.signal_pipe[1], &ses.isserver, 1) == 1 + || errno != EINTR) { + break; + } + } } - sa_chld.sa_handler = sesssigchild_handler; sa_chld.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &sa_chld, NULL); @@ -131,7 +142,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; @@ -170,10 +180,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 @@ -245,16 +256,17 @@ static void closechansess(struct Channel *channel) { unsigned int i; struct logininfo *li; - chansess = (struct ChanSess*)channel->typedata; + TRACE(("enter closechansess")) - send_exitsignalstatus(channel); + chansess = (struct ChanSess*)channel->typedata; - TRACE(("enter closechansess")) if (chansess == NULL) { TRACE(("leave closechansess: chansess == NULL")) return; } + send_exitsignalstatus(channel); + m_free(chansess->cmd); m_free(chansess->term); @@ -282,7 +294,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; } @@ -646,6 +658,12 @@ static int noptycommand(struct Channel *channel, struct ChanSess *chansess) { if (!pid) { /* child */ + TRACE(("back to normal sigchld")) + /* Revert to normal sigchld handling */ + if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) { + dropbear_exit("signal() error"); + } + /* redirect stdin/stdout */ #define FDIN 0 #define FDOUT 1 @@ -670,22 +688,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]); @@ -741,6 +761,12 @@ static int ptycommand(struct Channel *channel, struct ChanSess *chansess) { if (pid == 0) { /* child */ + TRACE(("back to normal sigchld")) + /* Revert to normal sigchld handling */ + if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) { + dropbear_exit("signal() error"); + } + /* redirect stdin/stdout/stderr */ close(chansess->master); |