summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/serverloop.c b/serverloop.c
index 1fa1f5800..c876dc0ca 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.86 2001/12/19 07:18:56 deraadt Exp $"); 38RCSID("$OpenBSD: serverloop.c,v 1.87 2001/12/19 16:09:39 markus Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "packet.h" 41#include "packet.h"
@@ -92,6 +92,51 @@ static volatile sig_atomic_t child_terminated = 0; /* The child has terminated.
92/* prototypes */ 92/* prototypes */
93static void server_init_dispatch(void); 93static void server_init_dispatch(void);
94 94
95/*
96 * we write to this pipe if a SIGCHLD is caught in order to avoid
97 * the race between select() and child_terminated
98 */
99static int notify_pipe[2];
100static void
101notify_setup(void)
102{
103 if (pipe(notify_pipe) < 0) {
104 error("pipe(notify_pipe) failed %s", strerror(errno));
105 } else if ((fcntl(notify_pipe[0], F_SETFD, 1) == -1) ||
106 (fcntl(notify_pipe[1], F_SETFD, 1) == -1)) {
107 error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
108 close(notify_pipe[0]);
109 close(notify_pipe[1]);
110 } else {
111 set_nonblock(notify_pipe[0]);
112 set_nonblock(notify_pipe[1]);
113 return;
114 }
115 notify_pipe[0] = -1; /* read end */
116 notify_pipe[1] = -1; /* write end */
117}
118static void
119notify_parent(void)
120{
121 if (notify_pipe[1] != -1)
122 write(notify_pipe[1], "", 1);
123}
124static void
125notify_prepare(fd_set *readset)
126{
127 if (notify_pipe[0] != -1)
128 FD_SET(notify_pipe[0], readset);
129}
130static void
131notify_done(fd_set *readset)
132{
133 char c;
134
135 if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
136 while (read(notify_pipe[0], &c, 1) != -1)
137 debug2("notify_done: reading");
138}
139
95static void 140static void
96sigchld_handler(int sig) 141sigchld_handler(int sig)
97{ 142{
@@ -99,6 +144,7 @@ sigchld_handler(int sig)
99 debug("Received SIGCHLD."); 144 debug("Received SIGCHLD.");
100 child_terminated = 1; 145 child_terminated = 1;
101 mysignal(SIGCHLD, sigchld_handler); 146 mysignal(SIGCHLD, sigchld_handler);
147 notify_parent();
102 errno = save_errno; 148 errno = save_errno;
103} 149}
104 150
@@ -242,6 +288,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
242 if (fdin != -1 && buffer_len(&stdin_buffer) > 0) 288 if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
243 FD_SET(fdin, *writesetp); 289 FD_SET(fdin, *writesetp);
244 } 290 }
291 notify_prepare(*readsetp);
245 292
246 /* 293 /*
247 * If we have buffered packet data going to the client, mark that 294 * If we have buffered packet data going to the client, mark that
@@ -279,6 +326,8 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
279 error("select: %.100s", strerror(errno)); 326 error("select: %.100s", strerror(errno));
280 } else if (ret == 0 && client_alive_scheduled) 327 } else if (ret == 0 && client_alive_scheduled)
281 client_alive_check(); 328 client_alive_check();
329
330 notify_done(*readsetp);
282} 331}
283 332
284/* 333/*
@@ -468,6 +517,8 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
468 connection_in = packet_get_connection_in(); 517 connection_in = packet_get_connection_in();
469 connection_out = packet_get_connection_out(); 518 connection_out = packet_get_connection_out();
470 519
520 notify_setup();
521
471 previous_stdout_buffer_bytes = 0; 522 previous_stdout_buffer_bytes = 0;
472 523
473 /* Set approximate I/O buffer size. */ 524 /* Set approximate I/O buffer size. */
@@ -573,6 +624,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
573 max_fd = MAX(max_fd, fdin); 624 max_fd = MAX(max_fd, fdin);
574 max_fd = MAX(max_fd, fdout); 625 max_fd = MAX(max_fd, fdout);
575 max_fd = MAX(max_fd, fderr); 626 max_fd = MAX(max_fd, fderr);
627 max_fd = MAX(max_fd, notify_pipe[0]);
576 628
577 /* Sleep in select() until we can do something. */ 629 /* Sleep in select() until we can do something. */
578 wait_until_can_do_something(&readset, &writeset, &max_fd, 630 wait_until_can_do_something(&readset, &writeset, &max_fd,
@@ -697,7 +749,11 @@ server_loop2(Authctxt *authctxt)
697 connection_in = packet_get_connection_in(); 749 connection_in = packet_get_connection_in();
698 connection_out = packet_get_connection_out(); 750 connection_out = packet_get_connection_out();
699 751
752 notify_setup();
753
700 max_fd = MAX(connection_in, connection_out); 754 max_fd = MAX(connection_in, connection_out);
755 max_fd = MAX(max_fd, notify_pipe[0]);
756
701 xxx_authctxt = authctxt; 757 xxx_authctxt = authctxt;
702 758
703 server_init_dispatch(); 759 server_init_dispatch();