mirror of
https://github.com/clearml/dropbear
synced 2025-06-09 07:58:15 +00:00
progress towards exiting on writefd closure rather than
on process exit - dbclient hangs with scp, so requires work. --HG-- extra : convert_revision : 2186a678a5f79ef432f6593a10e3e13df2a313d5
This commit is contained in:
parent
c9d3c0bc90
commit
e8fa3ce478
@ -181,6 +181,7 @@ void channelio(fd_set *readfds, fd_set *writefds) {
|
|||||||
|
|
||||||
struct Channel *channel;
|
struct Channel *channel;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* iterate through all the possible channels */
|
/* iterate through all the possible channels */
|
||||||
for (i = 0; i < ses.chansize; i++) {
|
for (i = 0; i < ses.chansize; i++) {
|
||||||
@ -204,7 +205,8 @@ void channelio(fd_set *readfds, fd_set *writefds) {
|
|||||||
|
|
||||||
/* if we can read from the writefd, it might be closed, so we try to
|
/* if we can read from the writefd, it might be closed, so we try to
|
||||||
* see if it has errors */
|
* see if it has errors */
|
||||||
if (channel->writefd >= 0 && channel->writefd != channel->readfd
|
if (IS_DROPBEAR_SERVER && channel->writefd >= 0
|
||||||
|
&& channel->writefd != channel->readfd
|
||||||
&& FD_ISSET(channel->writefd, readfds)) {
|
&& FD_ISSET(channel->writefd, readfds)) {
|
||||||
if (channel->initconn) {
|
if (channel->initconn) {
|
||||||
/* Handling for "in progress" connection - this is needed
|
/* Handling for "in progress" connection - this is needed
|
||||||
@ -259,28 +261,28 @@ static void checkclose(struct Channel *channel) {
|
|||||||
channel->writebuf,
|
channel->writebuf,
|
||||||
channel->writebuf ? 0 : cbuf_getused(channel->extrabuf)))
|
channel->writebuf ? 0 : cbuf_getused(channel->extrabuf)))
|
||||||
|
|
||||||
if (!channel->sentclosed) {
|
/* server chansession channels are special, since readfd mightn't
|
||||||
|
* close in the case of "sleep 4 & echo blah" until the sleep is up */
|
||||||
/* check for exited - currently only used for server sessions,
|
|
||||||
* if the shell has exited etc */
|
|
||||||
if (channel->type->checkclose) {
|
if (channel->type->checkclose) {
|
||||||
if (channel->type->checkclose(channel)) {
|
if (channel->type->checkclose(channel)) {
|
||||||
closewritefd(channel);
|
closewritefd(channel);
|
||||||
|
closereadfd(channel, channel->readfd);
|
||||||
|
closereadfd(channel, channel->errfd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!channel->senteof
|
if (!channel->senteof
|
||||||
&& channel->readfd == FD_CLOSED
|
&& channel->readfd == FD_CLOSED
|
||||||
&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
|
&& (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) {
|
||||||
send_msg_channel_eof(channel);
|
send_msg_channel_eof(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel->writefd == FD_CLOSED
|
if (!channel->sentclosed
|
||||||
|
&& channel->writefd == FD_CLOSED
|
||||||
&& channel->readfd == FD_CLOSED
|
&& channel->readfd == FD_CLOSED
|
||||||
&& (channel->extrabuf != NULL || channel->errfd == FD_CLOSED)) {
|
&& (channel->extrabuf == NULL || channel->errfd == FD_CLOSED)) {
|
||||||
send_msg_channel_close(channel);
|
send_msg_channel_close(channel);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* When either party wishes to terminate the channel, it sends
|
/* When either party wishes to terminate the channel, it sends
|
||||||
* SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST
|
* SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST
|
||||||
@ -444,20 +446,22 @@ void setchannelfds(fd_set *readfds, fd_set *writefds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For checking FD status (ie closure etc) - we don't actually
|
|
||||||
* read data from writefd */
|
|
||||||
TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d",
|
TRACE(("writefd = %d, readfd %d, errfd %d, bufused %d",
|
||||||
channel->writefd, channel->readfd,
|
channel->writefd, channel->readfd,
|
||||||
channel->errfd,
|
channel->errfd,
|
||||||
cbuf_getused(channel->writebuf) ))
|
cbuf_getused(channel->writebuf) ))
|
||||||
if (channel->writefd >= 0 && channel->writefd != channel->readfd) {
|
|
||||||
|
/* For checking FD status (ie closure etc) - we don't actually
|
||||||
|
* read data from writefd. We don't want to do this for the client,
|
||||||
|
* since redirection to /dev/null will make it spin in the select */
|
||||||
|
if (IS_DROPBEAR_SERVER && channel->writefd >= 0
|
||||||
|
&& channel->writefd != channel->readfd) {
|
||||||
FD_SET(channel->writefd, readfds);
|
FD_SET(channel->writefd, readfds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stuff from the wire, to local program/shell/user etc */
|
/* Stuff from the wire */
|
||||||
if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
|
if ((channel->writefd >= 0 && cbuf_getused(channel->writebuf) > 0 )
|
||||||
|| channel->initconn) {
|
|| channel->initconn) {
|
||||||
|
|
||||||
FD_SET(channel->writefd, writefds);
|
FD_SET(channel->writefd, writefds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@ static void get_termmodes(struct ChanSess *chansess);
|
|||||||
extern char** environ;
|
extern char** environ;
|
||||||
|
|
||||||
static int sesscheckclose(struct Channel *channel) {
|
static int sesscheckclose(struct Channel *channel) {
|
||||||
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
|
return channel->writefd == -1;
|
||||||
return chansess->exit.exitpid >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handler for childs exiting, store the state for return to the client */
|
/* Handler for childs exiting, store the state for return to the client */
|
||||||
|
Loading…
Reference in New Issue
Block a user