diff options
author | Matt Johnston <matt@ucc.asn.au> | 2007-02-22 14:53:49 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2007-02-22 14:53:49 +0000 |
commit | b01a74a9d757ce2b83465214bde1fa07d3e2d3ea (patch) | |
tree | 092cac6797947f7b23fcdcc2c081b19c390c5bc4 /common-session.c | |
parent | 66643fa5c723da2dc781c5eeae2e008c280a7b1c (diff) | |
parent | 7f12251fbb2acefac04e13a7c6a95ca4dd4b5578 (diff) |
merge of 'a9b0496634cdd25647b65e585cc3240f3fa699ee'
and 'c22be8b8f570b48e9662dac32c7b3e7148a42206'
--HG--
extra : convert_revision : 066f6aef2791d54b9ec6a0c3033fd28fa946251f
Diffstat (limited to 'common-session.c')
-rw-r--r-- | common-session.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/common-session.c b/common-session.c index 4c15391..6e1abf3 100644 --- a/common-session.c +++ b/common-session.c @@ -61,6 +61,12 @@ void common_session_init(int sock, char* remotehost) { ses.connecttimeout = 0; + if (pipe(ses.signal_pipe) < 0) { + dropbear_exit("signal pipe failed"); + } + setnonblocking(ses.signal_pipe[0]); + setnonblocking(ses.signal_pipe[1]); + kexfirstinitialise(); /* initialise the kex state */ ses.writepayload = buf_new(MAX_TRANS_PAYLOAD_LEN); @@ -108,7 +114,6 @@ void common_session_init(int sock, char* remotehost) { ses.allowprivport = 0; - TRACE(("leave session_init")) } @@ -132,6 +137,10 @@ void session_loop(void(*loophandler)()) { FD_SET(ses.sock, &writefd); } } + + /* We get woken up when signal handlers write to this pipe. + SIGCHLD in svr-chansession is the only one currently. */ + FD_SET(ses.signal_pipe[0], &readfd); /* set up for channels which require reading/writing */ if (ses.dataallowed) { @@ -143,28 +152,30 @@ void session_loop(void(*loophandler)()) { dropbear_exit("Terminated by signal"); } - if (val < 0) { - if (errno == EINTR) { - /* This must happen even if we've been interrupted, so that - * changed signal-handler vars can take effect etc */ - if (loophandler) { - loophandler(); - } - continue; - } else { - dropbear_exit("Error in select"); - } + if (val < 0 && errno != EINTR) { + dropbear_exit("Error in select"); } - /* check for auth timeout, rekeying required etc */ - checktimeouts(); + if (val <= 0) { + /* If we were interrupted or the select timed out, we still + * want to iterate over channels etc for reading, to handle + * server processes exiting etc. + * We don't want to read/write FDs. */ + FD_ZERO(&writefd); + FD_ZERO(&readfd); + } - if (val == 0) { - /* timeout */ - TRACE(("select timeout")) - continue; + /* We'll just empty out the pipe if required. We don't do + any thing with the data, since the pipe's purpose is purely to + wake up the select() above. */ + if (FD_ISSET(ses.signal_pipe[0], &readfd)) { + char x; + while (read(ses.signal_pipe[0], &x, 1) > 0) {} } + /* check for auth timeout, rekeying required etc */ + checktimeouts(); + /* process session socket's incoming/outgoing data */ if (ses.sock != -1) { if (FD_ISSET(ses.sock, &writefd) && !isempty(&ses.writequeue)) { @@ -229,7 +240,7 @@ void session_identification() { /* write our version string, this blocks */ if (atomicio(write, ses.sock, LOCAL_IDENT "\r\n", strlen(LOCAL_IDENT "\r\n")) == DROPBEAR_FAILURE) { - dropbear_exit("Error writing ident string"); + ses.remoteclosed(); } /* If they send more than 50 lines, something is wrong */ @@ -250,7 +261,7 @@ void session_identification() { if (!done) { TRACE(("err: %s for '%s'\n", strerror(errno), linebuf)) - dropbear_exit("Failed to get remote version"); + ses.remoteclosed(); } else { /* linebuf is already null terminated */ ses.remoteident = m_malloc(len); |