summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--serverloop.c58
2 files changed, 64 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 3b9814f51..7b8212505 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -38,6 +38,12 @@
38 [sshconnect1.c sshconnect2.c sshconnect.c sshd.8 sshd.c sshd_config] 38 [sshconnect1.c sshconnect2.c sshconnect.c sshd.8 sshd.c sshd_config]
39 [ssh-keygen.c sshlogin.c sshpty.c sshtty.c ttymodes.c uidswap.c] 39 [ssh-keygen.c sshlogin.c sshpty.c sshtty.c ttymodes.c uidswap.c]
40 basic KNF done while i was looking for something else 40 basic KNF done while i was looking for something else
41 - markus@cvs.openbsd.org 2001/12/19 16:09:39
42 [serverloop.c]
43 fix race between SIGCHLD and select with an additional pipe. writing
44 to the pipe on SIGCHLD wakes up select(). using pselect() is not
45 portable and siglongjmp() ugly. W. R. Stevens suggests similar solution.
46 initial idea by pmenage@ensim.com; ok deraadt@, djm@
41 47
4220011219 4820011219
43 - (stevesk) OpenBSD CVS sync X11 localhost display 49 - (stevesk) OpenBSD CVS sync X11 localhost display
@@ -7066,4 +7072,4 @@
7066 - Wrote replacements for strlcpy and mkdtemp 7072 - Wrote replacements for strlcpy and mkdtemp
7067 - Released 1.0pre1 7073 - Released 1.0pre1
7068 7074
7069$Id: ChangeLog,v 1.1701 2001/12/21 03:45:46 djm Exp $ 7075$Id: ChangeLog,v 1.1702 2001/12/21 03:53:11 djm Exp $
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();