[Bug 52] ssh hangs on exit
bugzilla-daemon at mindrot.org
bugzilla-daemon at mindrot.org
Sun Jan 21 15:54:22 EST 2007
http://bugzilla.mindrot.org/show_bug.cgi?id=52
------- Comment #33 from djm at mindrot.org 2007-01-21 15:54 -------
(From update of attachment 1215)
Sorry for taking so long to review this. Some comments on the diff (I'd
really like to see this in 4.6p1)
>Index: channels.c
>===================================================================
>RCS file: /usr/local/src/security/openssh/cvs/openssh/channels.c,v
>retrieving revision 1.248
>diff -u -p -r1.248 channels.c
>--- channels.c 30 Aug 2006 01:07:40 -0000 1.248
>+++ channels.c 27 Nov 2006 03:39:26 -0000
>@@ -1449,10 +1449,10 @@ channel_handle_rfd(Channel *c, fd_set *r
> int len;
>
> if (c->rfd != -1 &&
>- FD_ISSET(c->rfd, readset)) {
>+ (c->detach_close || FD_ISSET(c->rfd, readset))) {
Is c->detach_close used here to chose "session channels that have
exitied but not yet closed"? or something else?
> errno = 0;
> len = read(c->rfd, buf, sizeof(buf));
>- if (len < 0 && (errno == EINTR || errno == EAGAIN))
>+ if (len < 0 && errno == EINTR)
Can the second condition instead be made:
&& (errno == EINTR || c->detach_close || errno == EAGAIN)
This would limit the scope of the change to only session channels which
have already received a SIGCHLD.
>@@ -1604,11 +1604,11 @@ channel_handle_efd(Channel *c, fd_set *r
> c->local_consumed += len;
> }
> } else if (c->extended_usage == CHAN_EXTENDED_READ &&
>- FD_ISSET(c->efd, readset)) {
>+ (c->detach_close || FD_ISSET(c->efd, readset))) {
> len = read(c->efd, buf, sizeof(buf));
> debug2("channel %d: read %d from efd %d",
> c->self, len, c->efd);
>- if (len < 0 && (errno == EINTR || errno == EAGAIN))
>+ if (len < 0 && errno == EINTR)
Likewise.
>Index: serverloop.c
>===================================================================
>RCS file: /usr/local/src/security/openssh/cvs/openssh/serverloop.c,v
>retrieving revision 1.150
>diff -u -p -r1.150 serverloop.c
>--- serverloop.c 23 Oct 2006 17:02:41 -0000 1.150
>+++ serverloop.c 27 Nov 2006 03:37:16 -0000
>@@ -280,6 +280,7 @@ wait_until_can_do_something(fd_set **rea
> struct timeval tv, *tvp;
> int ret;
> int client_alive_scheduled = 0;
>+ int program_alive_scheduled = 0;
>
> /*
> * if using client_alive, set the max timeout accordingly,
>@@ -317,6 +318,7 @@ wait_until_can_do_something(fd_set **rea
> * the client, try to get some more data from the program.
> */
> if (packet_not_very_much_data_to_write()) {
>+ program_alive_scheduled = child_terminated;
Why not just use child_terminated directly here? Is it because of
children exiting during select()
>- } else if (ret == 0 && client_alive_scheduled)
>- client_alive_check();
>+ } else {
>+ if (ret == 0 && client_alive_scheduled)
>+ client_alive_check();
>+ if (program_alive_scheduled && fdin_is_tty) {
>+ if (!fdout_eof)
>+ FD_SET(fdout, *readsetp);
>+ if (!fderr_eof)
>+ FD_SET(fderr, *readsetp);
>+ }
>+ }
I think the condition for this if() should include !compat20 (I know
that fdin_is_tty is never set for !compat20, but you have to hunt for
it).
>
> notify_done(*readsetp);
> }
>@@ -407,7 +417,7 @@ process_input(fd_set *readset)
> if (!fdout_eof && FD_ISSET(fdout, readset)) {
> errno = 0;
> len = read(fdout, buf, sizeof(buf));
>- if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
>+ if (len < 0 && errno == EINTR) {
> /* do nothing */
> #ifndef PTY_ZEROREAD
> } else if (len <= 0) {
>@@ -425,7 +435,7 @@ process_input(fd_set *readset)
> if (!fderr_eof && FD_ISSET(fderr, readset)) {
> errno = 0;
> len = read(fderr, buf, sizeof(buf));
>- if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
>+ if (len < 0 && errno == EINTR) {
similar comment as for channels.c bit: can we use program_terminated
here instead of c->detach close?
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
More information about the openssh-bugs
mailing list