summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c55
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"
38RCSID("$OpenBSD: serverloop.c,v 1.67 2001/05/31 10:30:16 markus Exp $"); 38RCSID("$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
88static pid_t child_pid; /* Pid of the child. */
89static volatile int child_terminated; /* The child has terminated. */ 87static volatile int child_terminated; /* The child has terminated. */
90static volatile int child_wait_status; /* Status from wait(). */
91 88
92void server_init_dispatch(void); 89void server_init_dispatch(void);
93 90
@@ -97,28 +94,9 @@ void
97sigchld_handler(int sig) 94sigchld_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}
115void
116sigchld_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();