diff options
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 55 |
1 files changed, 10 insertions, 45 deletions
diff --git a/serverloop.c b/serverloop.c index d8026ec5a..bafbfb0ac 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.67 2001/05/31 10:30:16 markus Exp $"); | 38 | RCSID("$OpenBSD: serverloop.c,v 1.68 2001/06/04 23:07:20 markus Exp $"); |
39 | 39 | ||
40 | #include "xmalloc.h" | 40 | #include "xmalloc.h" |
41 | #include "packet.h" | 41 | #include "packet.h" |
@@ -84,10 +84,7 @@ static u_int buffer_high; /* "Soft" max buffer size. */ | |||
84 | * This SIGCHLD kludge is used to detect when the child exits. The server | 84 | * This SIGCHLD kludge is used to detect when the child exits. The server |
85 | * will exit after that, as soon as forwarded connections have terminated. | 85 | * will exit after that, as soon as forwarded connections have terminated. |
86 | */ | 86 | */ |
87 | |||
88 | static pid_t child_pid; /* Pid of the child. */ | ||
89 | static volatile int child_terminated; /* The child has terminated. */ | 87 | static volatile int child_terminated; /* The child has terminated. */ |
90 | static volatile int child_wait_status; /* Status from wait(). */ | ||
91 | 88 | ||
92 | void server_init_dispatch(void); | 89 | void server_init_dispatch(void); |
93 | 90 | ||
@@ -97,28 +94,9 @@ void | |||
97 | sigchld_handler(int sig) | 94 | sigchld_handler(int sig) |
98 | { | 95 | { |
99 | int save_errno = errno; | 96 | int save_errno = errno; |
100 | pid_t wait_pid; | ||
101 | |||
102 | debug("Received SIGCHLD."); | ||
103 | wait_pid = wait((int *) &child_wait_status); | ||
104 | if (wait_pid != -1) { | ||
105 | if (wait_pid != child_pid) | ||
106 | error("Strange, got SIGCHLD and wait returned pid %d but child is %d", | ||
107 | wait_pid, child_pid); | ||
108 | if (WIFEXITED(child_wait_status) || | ||
109 | WIFSIGNALED(child_wait_status)) | ||
110 | child_terminated = 1; | ||
111 | } | ||
112 | signal(SIGCHLD, sigchld_handler); | ||
113 | errno = save_errno; | ||
114 | } | ||
115 | void | ||
116 | sigchld_handler2(int sig) | ||
117 | { | ||
118 | int save_errno = errno; | ||
119 | debug("Received SIGCHLD."); | 97 | debug("Received SIGCHLD."); |
120 | child_terminated = 1; | 98 | child_terminated = 1; |
121 | mysignal(SIGCHLD, sigchld_handler2); | 99 | mysignal(SIGCHLD, sigchld_handler); |
122 | errno = save_errno; | 100 | errno = save_errno; |
123 | } | 101 | } |
124 | 102 | ||
@@ -466,7 +444,6 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
466 | debug("Entering interactive session."); | 444 | debug("Entering interactive session."); |
467 | 445 | ||
468 | /* Initialize the SIGCHLD kludge. */ | 446 | /* Initialize the SIGCHLD kludge. */ |
469 | child_pid = pid; | ||
470 | child_terminated = 0; | 447 | child_terminated = 0; |
471 | signal(SIGCHLD, sigchld_handler); | 448 | signal(SIGCHLD, sigchld_handler); |
472 | 449 | ||
@@ -634,28 +611,16 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) | |||
634 | /* Stop listening for channels; this removes unix domain sockets. */ | 611 | /* Stop listening for channels; this removes unix domain sockets. */ |
635 | channel_stop_listening(); | 612 | channel_stop_listening(); |
636 | 613 | ||
637 | /* Wait for the child to exit. Get its exit status. */ | ||
638 | wait_pid = wait(&wait_status); | ||
639 | if (wait_pid == -1) { | ||
640 | /* | ||
641 | * It is possible that the wait was handled by SIGCHLD | ||
642 | * handler. This may result in either: this call | ||
643 | * returning with EINTR, or: this call returning ECHILD. | ||
644 | */ | ||
645 | if (child_terminated) | ||
646 | wait_status = child_wait_status; | ||
647 | else | ||
648 | packet_disconnect("wait: %.100s", strerror(errno)); | ||
649 | } else { | ||
650 | /* Check if it matches the process we forked. */ | ||
651 | if (wait_pid != pid) | ||
652 | error("Strange, wait returned pid %d, expected %d", | ||
653 | wait_pid, pid); | ||
654 | } | ||
655 | |||
656 | /* We no longer want our SIGCHLD handler to be called. */ | 614 | /* We no longer want our SIGCHLD handler to be called. */ |
657 | signal(SIGCHLD, SIG_DFL); | 615 | signal(SIGCHLD, SIG_DFL); |
658 | 616 | ||
617 | wait_pid = waitpid(-1, &wait_status, child_terminated ? WNOHANG : 0); | ||
618 | if (wait_pid == -1) | ||
619 | packet_disconnect("wait: %.100s", strerror(errno)); | ||
620 | else if (wait_pid != pid) | ||
621 | error("Strange, wait returned pid %d, expected %d", | ||
622 | wait_pid, pid); | ||
623 | |||
659 | /* Check if it exited normally. */ | 624 | /* Check if it exited normally. */ |
660 | if (WIFEXITED(wait_status)) { | 625 | if (WIFEXITED(wait_status)) { |
661 | /* Yes, normal exit. Get exit status and send it to the client. */ | 626 | /* Yes, normal exit. Get exit status and send it to the client. */ |
@@ -700,7 +665,7 @@ server_loop2(void) | |||
700 | 665 | ||
701 | debug("Entering interactive session for SSH2."); | 666 | debug("Entering interactive session for SSH2."); |
702 | 667 | ||
703 | mysignal(SIGCHLD, sigchld_handler2); | 668 | mysignal(SIGCHLD, sigchld_handler); |
704 | child_terminated = 0; | 669 | child_terminated = 0; |
705 | connection_in = packet_get_connection_in(); | 670 | connection_in = packet_get_connection_in(); |
706 | connection_out = packet_get_connection_out(); | 671 | connection_out = packet_get_connection_out(); |