mirror of
https://github.com/clearml/dropbear
synced 2025-02-07 05:17:28 +00:00
Bring back recently removed channel->flushing
This resolves the "sleep 10&echo hello" case which should return immediately
This commit is contained in:
parent
043b0fbd1b
commit
a7ef149463
@ -71,6 +71,9 @@ struct Channel {
|
||||
/* whether close/eof messages have been exchanged */
|
||||
int sent_close, recv_close;
|
||||
int recv_eof, sent_eof;
|
||||
/* once flushing is set, readfd will close once no more data is available
|
||||
(not waiting for EOF) */
|
||||
int flushing;
|
||||
|
||||
struct dropbear_progress_connection *conn_pending;
|
||||
int initconn; /* used for TCP forwarding, whether the channel has been
|
||||
@ -93,9 +96,9 @@ struct ChanType {
|
||||
const char *name;
|
||||
/* Sets up the channel */
|
||||
int (*inithandler)(struct Channel*);
|
||||
/* Called to check whether a channel should close, separately from the FD being closed.
|
||||
/* Called to check whether a channel should close, separately from the FD being EOF.
|
||||
Used for noticing process exiting */
|
||||
int (*check_close)(const struct Channel*);
|
||||
int (*check_close)(struct Channel*);
|
||||
/* Handler for ssh_msg_channel_request */
|
||||
void (*reqhandler)(struct Channel*);
|
||||
/* Called prior to sending ssh_msg_channel_close, used for sending exit status */
|
||||
|
@ -293,6 +293,19 @@ static void check_close(struct Channel *channel) {
|
||||
close_allowed = 1;
|
||||
}
|
||||
|
||||
/* In flushing mode we close FDs as soon as pipes are empty.
|
||||
This is used to drain out FDs when the process exits, in the case
|
||||
where the FD doesn't have EOF - "sleep 10&echo hello" case */
|
||||
if (channel->flushing) {
|
||||
if (channel->readfd >= 0 && !fd_read_pending(channel->readfd)) {
|
||||
close_chan_fd(channel, channel->readfd, SHUT_RD);
|
||||
}
|
||||
if (ERRFD_IS_READ(channel)
|
||||
&& channel->errfd >= 0 && !fd_read_pending(channel->errfd)) {
|
||||
close_chan_fd(channel, channel->errfd, SHUT_RD);
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->recv_close && !write_pending(channel) && close_allowed) {
|
||||
if (!channel->sent_close) {
|
||||
TRACE(("Sending MSG_CHANNEL_CLOSE in response to same."))
|
||||
|
19
dbutil.c
19
dbutil.c
@ -715,3 +715,22 @@ void fsync_parent_dir(const char* fn) {
|
||||
m_free(fn_dir);
|
||||
#endif
|
||||
}
|
||||
|
||||
int fd_read_pending(int fd) {
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
|
||||
DROPBEAR_FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
while (1) {
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
if (select(fd+1, &fds, NULL, NULL, &timeout) < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return FD_ISSET(fd, &fds);
|
||||
}
|
||||
}
|
||||
|
2
dbutil.h
2
dbutil.h
@ -90,6 +90,8 @@ char * expand_homedir_path(const char *inpath);
|
||||
|
||||
void fsync_parent_dir(const char* fn);
|
||||
|
||||
int fd_read_pending(int fd);
|
||||
|
||||
#if DROPBEAR_MSAN
|
||||
/* FD_ZERO seems to leave some memory uninitialized. clear it to avoid false positives */
|
||||
#define DROPBEAR_FD_ZERO(fds) do { memset((fds), 0x0, sizeof(fd_set)); FD_ZERO(fds); } while(0)
|
||||
|
@ -54,7 +54,7 @@ static void closechansess(const struct Channel *channel);
|
||||
static void cleanupchansess(const struct Channel *channel);
|
||||
static int newchansess(struct Channel *channel);
|
||||
static void chansessionrequest(struct Channel *channel);
|
||||
static int sesscheckclose(const struct Channel *channel);
|
||||
static int sesscheckclose(struct Channel *channel);
|
||||
|
||||
static void send_exitsignalstatus(const struct Channel *channel);
|
||||
static void send_msg_chansess_exitstatus(const struct Channel * channel,
|
||||
@ -77,9 +77,13 @@ extern char** environ;
|
||||
|
||||
/* Returns whether the channel is ready to close. The child process
|
||||
must not be running (has never started, or has exited) */
|
||||
static int sesscheckclose(const struct Channel *channel) {
|
||||
static int sesscheckclose(struct Channel *channel) {
|
||||
struct ChanSess *chansess = (struct ChanSess*)channel->typedata;
|
||||
TRACE(("sesscheckclose, pid %d, exitpid %d", chansess->pid, chansess->exit.exitpid))
|
||||
|
||||
if (chansess->exit.exitpid != -1) {
|
||||
channel->flushing = 1;
|
||||
}
|
||||
return chansess->pid == 0 || chansess->exit.exitpid != -1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user