diff options
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 38 |
1 files changed, 15 insertions, 23 deletions
diff --git a/serverloop.c b/serverloop.c index d7282fe2a..8a82af55b 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "includes.h" | 37 | #include "includes.h" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.80 2001/10/09 19:51:18 markus Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.81 2001/10/09 21:59:41 markus Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "packet.h" | 41 | #include "packet.h" |
@@ -674,6 +674,7 @@ server_loop2(Authctxt *authctxt) | |||
674 | fd_set *readset = NULL, *writeset = NULL; | 674 | fd_set *readset = NULL, *writeset = NULL; |
675 | int rekeying = 0, max_fd, status, nalloc = 0; | 675 | int rekeying = 0, max_fd, status, nalloc = 0; |
676 | pid_t pid; | 676 | pid_t pid; |
677 | sigset_t oset, nset; | ||
677 | 678 | ||
678 | debug("Entering interactive session for SSH2."); | 679 | debug("Entering interactive session for SSH2."); |
679 | 680 | ||
@@ -696,12 +697,17 @@ server_loop2(Authctxt *authctxt) | |||
696 | channel_output_poll(); | 697 | channel_output_poll(); |
697 | wait_until_can_do_something(&readset, &writeset, &max_fd, | 698 | wait_until_can_do_something(&readset, &writeset, &max_fd, |
698 | &nalloc, 0); | 699 | &nalloc, 0); |
700 | |||
701 | /* block SIGCHLD while we check for dead children */ | ||
702 | sigemptyset(&nset); | ||
703 | sigaddset(&nset, SIGCHLD); | ||
704 | sigprocmask(SIG_BLOCK, &nset, &oset); | ||
699 | if (child_terminated) { | 705 | if (child_terminated) { |
700 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | 706 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) |
701 | session_close_by_pid(pid, status); | 707 | session_close_by_pid(pid, status); |
702 | /* XXX race */ | ||
703 | child_terminated = 0; | 708 | child_terminated = 0; |
704 | } | 709 | } |
710 | sigprocmask(SIG_SETMASK, &oset, NULL); | ||
705 | if (!rekeying) | 711 | if (!rekeying) |
706 | channel_after_select(readset, writeset); | 712 | channel_after_select(readset, writeset); |
707 | process_input(readset); | 713 | process_input(readset); |
@@ -709,35 +715,21 @@ server_loop2(Authctxt *authctxt) | |||
709 | break; | 715 | break; |
710 | process_output(writeset); | 716 | process_output(writeset); |
711 | } | 717 | } |
712 | /* close all channels, no more reads and writes */ | ||
713 | channel_close_all(); | ||
714 | |||
715 | if (readset) | 718 | if (readset) |
716 | xfree(readset); | 719 | xfree(readset); |
717 | if (writeset) | 720 | if (writeset) |
718 | xfree(writeset); | 721 | xfree(writeset); |
719 | 722 | ||
720 | mysignal(SIGCHLD, SIG_DFL); | 723 | /* free all channels, no more reads and writes */ |
724 | channel_free_all(); | ||
721 | 725 | ||
722 | /* collect dead children */ | 726 | /* collect remaining dead children, XXX not necessary? */ |
727 | mysignal(SIGCHLD, SIG_DFL); | ||
723 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) | 728 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0) |
724 | session_close_by_pid(pid, status); | 729 | session_close_by_pid(pid, status); |
725 | /* | 730 | |
726 | * there is a race between channel_detach_all() killing remaining | 731 | /* close remaining sessions, e.g remove wtmp entries */ |
727 | * children and children dying before kill() | 732 | session_close_all(); |
728 | */ | ||
729 | channel_detach_all(); | ||
730 | |||
731 | while (session_have_children()) { | ||
732 | pid = waitpid(-1, &status, 0); | ||
733 | if (pid > 0) | ||
734 | session_close_by_pid(pid, status); | ||
735 | else { | ||
736 | error("waitpid returned %d: %s", pid, strerror(errno)); | ||
737 | break; | ||
738 | } | ||
739 | } | ||
740 | channel_free_all(); | ||
741 | } | 733 | } |
742 | 734 | ||
743 | static void | 735 | static void |