diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | serverloop.c | 58 |
2 files changed, 64 insertions, 2 deletions
@@ -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 | ||
42 | 20011219 | 48 | 20011219 |
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" |
38 | RCSID("$OpenBSD: serverloop.c,v 1.86 2001/12/19 07:18:56 deraadt Exp $"); | 38 | RCSID("$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 */ |
93 | static void server_init_dispatch(void); | 93 | static 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 | */ | ||
99 | static int notify_pipe[2]; | ||
100 | static void | ||
101 | notify_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 | } | ||
118 | static void | ||
119 | notify_parent(void) | ||
120 | { | ||
121 | if (notify_pipe[1] != -1) | ||
122 | write(notify_pipe[1], "", 1); | ||
123 | } | ||
124 | static void | ||
125 | notify_prepare(fd_set *readset) | ||
126 | { | ||
127 | if (notify_pipe[0] != -1) | ||
128 | FD_SET(notify_pipe[0], readset); | ||
129 | } | ||
130 | static void | ||
131 | notify_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 | |||
95 | static void | 140 | static void |
96 | sigchld_handler(int sig) | 141 | sigchld_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(); |