Skip to content

Commit 56ad915

Browse files
committed
Missing SIGCHLD zombie logic
1 parent 327f077 commit 56ad915

File tree

7 files changed

+375
-279
lines changed

7 files changed

+375
-279
lines changed

contrib/win32/openssh/win32iocompat.vcxproj

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,9 @@
147147
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" />
148148
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" />
149149
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" />
150-
<ClCompile Include="..\win32compat\w32log.c" />
150+
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigalrm.c" />
151+
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_sigchld.c" />
152+
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32log.c" />
151153
</ItemGroup>
152154
<ItemGroup>
153155
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@@ -163,8 +165,9 @@
163165
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\w32posix.h" />
164166
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\poll.h" />
165167
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\sys\statvfs.h" />
166-
<ClInclude Include="..\win32compat\inc\dlfcn.h" />
167-
<ClInclude Include="..\win32compat\inc\syslog.h" />
168+
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\dlfcn.h" />
169+
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\inc\syslog.h" />
170+
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\signal_internal.h" />
168171
</ItemGroup>
169172
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
170173
<ImportGroup Label="ExtensionTargets">

contrib/win32/openssh/win32iocompat.vcxproj.filters

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\fileio.c" />
88
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\termio.c" />
99
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\misc.c" />
10-
<ClCompile Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\log.c" />
10+
<ClCompile Include="..\win32compat\w32log.c" />
11+
<ClCompile Include="..\win32compat\signal_sigchld.c" />
12+
<ClCompile Include="..\win32compat\signal_sigalrm.c" />
1113
</ItemGroup>
1214
<ItemGroup>
1315
<ClInclude Include="$(OpenSSH-Src-Path)\contrib\win32\win32compat\w32fd.h" />
@@ -53,6 +55,7 @@
5355
<ClInclude Include="..\win32compat\inc\dlfcn.h">
5456
<Filter>inc</Filter>
5557
</ClInclude>
58+
<ClInclude Include="..\win32compat\signal_internal.h" />
5659
</ItemGroup>
5760
<ItemGroup>
5861
<Filter Include="inc">

contrib/win32/win32compat/signal.c

Lines changed: 14 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include "w32fd.h"
3232
#include <errno.h>
3333
#include <signal.h>
34-
#include "inc\defs.h"
34+
#include "signal_internal.h"
3535

3636
/* pending signals to be processed */
3737
sigset_t pending_signals;
@@ -96,261 +96,7 @@ sw_init_signal_handler_table() {
9696
memset(sig_handlers, 0, sizeof(sig_handlers));
9797
}
9898

99-
/* child processes */
100-
#define MAX_CHILDREN 50
101-
struct _children {
102-
HANDLE handles[MAX_CHILDREN];
103-
DWORD process_id[MAX_CHILDREN];
104-
/* total children */
105-
DWORD num_children;
106-
/* #zombies */
107-
/* (num_chileren - zombies) are live children */
108-
DWORD num_zombies;
109-
} children;
110-
111-
int
112-
sw_add_child(HANDLE child, DWORD pid) {
113-
DWORD first_zombie_index;
114-
115-
debug("Register child %p pid %d, %d zombies of %d", child, pid,
116-
children.num_zombies, children.num_children);
117-
if (children.num_children == MAX_CHILDREN) {
118-
errno = ENOMEM;
119-
return -1;
120-
}
121-
if (children.num_zombies) {
122-
first_zombie_index = children.num_children - children.num_zombies;
123-
children.handles[children.num_children] = children.handles[first_zombie_index];
124-
children.process_id[children.num_children] = children.handles[first_zombie_index];
125-
126-
children.handles[first_zombie_index] = child;
127-
children.process_id[first_zombie_index] = pid;
128-
}
129-
else {
130-
children.handles[children.num_children] = child;
131-
children.process_id[children.num_children] = pid;
132-
}
133-
134-
135-
children.num_children++;
136-
return 0;
137-
}
138-
139-
int
140-
sw_remove_child_at_index(DWORD index) {
141-
DWORD last_non_zombie;
142-
143-
debug("Unregister child at index %d, %d zombies of %d", index,
144-
children.num_zombies, children.num_children);
145-
146-
if ((index >= children.num_children)
147-
|| (children.num_children == 0) ){
148-
errno = EINVAL;
149-
return -1;
150-
}
151-
152-
CloseHandle(children.handles[index]);
153-
if (children.num_zombies == 0) {
154-
children.handles[index] = children.handles[children.num_children - 1];
155-
children.process_id[index] = children.process_id[children.num_children - 1];
156-
}
157-
else {
158-
/* if its a zombie */
159-
if (index >= (children.num_children - children.num_zombies)) {
160-
children.handles[index] = children.handles[children.num_children - 1];
161-
children.process_id[index] = children.handles[children.num_children - 1];
162-
children.num_zombies--;
163-
}
164-
else {
165-
last_non_zombie = children.num_children - children.num_zombies - 1;
166-
children.handles[index] = children.handles[last_non_zombie];
167-
children.process_id[index] = children.process_id[last_non_zombie];
168-
169-
children.handles[last_non_zombie] = children.handles[children.num_children - 1];
170-
children.process_id[last_non_zombie] = children.handles[children.num_children - 1];
171-
}
172-
}
173-
174-
children.num_children--;
175-
return 0;
176-
}
177-
178-
int
179-
sw_child_to_zombie(DWORD index) {
180-
DWORD last_non_zombie;
181-
182-
debug("zombie'ing child at index %d, %d zombies of %d", index,
183-
children.num_zombies, children.num_children);
184-
185-
if (index >= children.num_children) {
186-
errno = EINVAL;
187-
return -1;
188-
}
189-
190-
/* TODO - turn child to zombie*/
191-
return 0;
192-
}
193-
194-
int
195-
sw_remove_child(HANDLE child) {
196-
HANDLE* handles = children.handles;
197-
DWORD num_children = children.num_children;
198-
199-
while (num_children) {
200-
if (*handles == child)
201-
return sw_remove_child_at_index(children.num_children - num_children);
202-
handles++;
203-
num_children--;
204-
}
205-
206-
errno = EINVAL;
207-
return -1;
208-
}
209-
210-
int waitpid(int pid, int *status, int options) {
211-
DWORD index, ret, ret_id, exit_code, timeout = 0;
212-
HANDLE process = NULL;
213-
214-
if (options & (~WNOHANG)) {
215-
errno = ENOTSUP;
216-
DebugBreak();
217-
return -1;
218-
}
219-
220-
if ((pid < -1) || (pid == 0)) {
221-
errno = ENOTSUP;
222-
DebugBreak();
223-
return -1;
224-
}
225-
226-
if (children.num_children == 0) {
227-
errno = ECHILD;
228-
return -1;
229-
}
230-
231-
if (pid > 0) {
232-
if (options != 0) {
233-
errno = ENOTSUP;
234-
DebugBreak();
235-
return -1;
236-
}
237-
/* find entry in table */
238-
for (index = 0; index < children.num_children; index++)
239-
if (children.process_id[index] == pid)
240-
break;
241-
242-
if (index == children.num_children) {
243-
errno = ECHILD;
244-
return -1;
245-
}
246-
247-
process = children.handles[index];
248-
ret = WaitForSingleObject(process, INFINITE);
249-
if (ret != WAIT_OBJECT_0)
250-
DebugBreak();//fatal
251-
252-
ret_id = children.process_id[index];
253-
GetExitCodeProcess(process, &exit_code);
254-
CloseHandle(process);
255-
sw_remove_child_at_index(index);
256-
if (status)
257-
*status = exit_code;
258-
return ret_id;
259-
}
260-
261-
/* pid = -1*/
262-
timeout = INFINITE;
263-
if (options & WNOHANG)
264-
timeout = 0;
265-
ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
266-
if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
267-
index = ret - WAIT_OBJECT_0;
268-
process = children.handles[index];
269-
ret_id = children.process_id[index];
270-
GetExitCodeProcess(process, &exit_code);
271-
CloseHandle(process);
272-
sw_remove_child_at_index(index);
273-
if (status)
274-
*status = exit_code;
275-
return ret_id;
276-
}
277-
else if (ret == WAIT_TIMEOUT) {
278-
/* assert that WNOHANG was specified*/
279-
return 0;
280-
}
281-
282-
DebugBreak();//fatal
283-
return -1;
284-
}
285-
286-
static void
287-
sw_cleanup_child_zombies() {
288-
int pid = 1;
289-
while (pid > 0) {
290-
pid = waitpid(-1, NULL, WNOHANG);
291-
}
292-
}
293-
294-
struct {
295-
HANDLE timer;
296-
ULONGLONG ticks_at_start; /* 0 if timer is not live */
297-
__int64 run_time_sec; /* time in seconds, timer is set to go off from ticks_at_start */
298-
} timer_info;
299-
300-
301-
VOID CALLBACK
302-
sigalrm_APC(
303-
_In_opt_ LPVOID lpArgToCompletionRoutine,
304-
_In_ DWORD dwTimerLowValue,
305-
_In_ DWORD dwTimerHighValue
306-
) {
307-
sigaddset(&pending_signals, W32_SIGALRM);
308-
}
309-
310-
unsigned int
311-
sw_alarm(unsigned int sec) {
312-
LARGE_INTEGER due;
313-
ULONGLONG sec_passed;
314-
int ret = 0;
315-
316-
errno = 0;
317-
/* cancel any live timer if seconds is 0*/
318-
if (sec == 0) {
319-
CancelWaitableTimer(timer_info.timer);
320-
timer_info.ticks_at_start = 0;
321-
timer_info.run_time_sec = 0;
322-
return 0;
323-
}
324-
325-
due.QuadPart = -10000000LL; //1 sec in 100 nanosec intervals
326-
due.QuadPart *= sec;
327-
/* this call resets the timer if it is already active */
328-
if (!SetWaitableTimer(timer_info.timer, &due, 0, sigalrm_APC, NULL, FALSE)) {
329-
debug("alram() - ERROR SetWaitableTimer() %d", GetLastError());
330-
return 0;;
331-
}
332-
333-
/* if timer was already ative, return when it was due */
334-
if (timer_info.ticks_at_start) {
335-
sec_passed = (GetTickCount64() - timer_info.ticks_at_start) / 1000;
336-
if (sec_passed < timer_info.run_time_sec)
337-
ret = timer_info.run_time_sec - sec_passed;
338-
}
339-
timer_info.ticks_at_start = GetTickCount64();
340-
timer_info.run_time_sec = sec;
341-
return ret;
342-
}
343-
344-
static int
345-
sw_init_timer() {
346-
memset(&timer_info, 0, sizeof(timer_info));
347-
timer_info.timer = CreateWaitableTimer(NULL, TRUE, NULL);
348-
if (timer_info.timer == NULL) {
349-
errno = ENOMEM;
350-
return -1;
351-
}
352-
return 0;
353-
}
99+
extern struct _children children;
354100

355101
sighandler_t
356102
sw_signal(int signum, sighandler_t handler) {
@@ -377,7 +123,7 @@ sw_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
377123
int
378124
sw_raise(int sig) {
379125
if (sig == W32_SIGSEGV)
380-
raise(SIGSEGV); /* raise native exception handler*/
126+
return raise(SIGSEGV); /* raise native exception handler*/
381127

382128
if (sig >= W32_SIGMAX) {
383129
errno = EINVAL;
@@ -432,7 +178,7 @@ sw_process_pending_signals() {
432178
/* check for expected signals*/
433179
for (i = 0; i < (sizeof(exp) / sizeof(exp[0])); i++)
434180
sigdelset(&pending_tmp, exp[i]);
435-
if (pending_tmp) {
181+
if (pending_tmp) {
436182
/* unexpected signals queued up */
437183
errno = ENOTSUP;
438184
DebugBreak();
@@ -448,6 +194,11 @@ sw_process_pending_signals() {
448194
sw_raise(exp[i]);
449195
sig_int = TRUE;
450196
}
197+
else { /* W32_SIG_IGN */
198+
/* for SIGCHLD process zombies */
199+
if (exp[i] == W32_SIGCHLD)
200+
sw_cleanup_child_zombies();
201+
}
451202

452203
sigdelset(&pending_tmp, exp[i]);
453204
}
@@ -485,8 +236,9 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
485236
{
486237
HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
487238
DWORD num_all_events;
239+
DWORD live_children = children.num_children - children.num_zombies;
488240

489-
num_all_events = num_events + children.num_children;
241+
num_all_events = num_events + live_children;
490242

491243
if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
492244
errno = ENOTSUP;
@@ -497,8 +249,8 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
497249
if (pending_signals)
498250
DebugBreak();
499251

500-
memcpy(all_events, children.handles, children.num_children * sizeof(HANDLE));
501-
memcpy(all_events + children.num_children, events, num_events * sizeof(HANDLE));
252+
memcpy(all_events, children.handles, live_children * sizeof(HANDLE));
253+
memcpy(all_events + live_children, events, num_events * sizeof(HANDLE));
502254

503255
/* TODO - implement signal catching and handling */
504256
if (num_all_events) {
@@ -507,11 +259,8 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
507259
if ((ret >= WAIT_OBJECT_0) && (ret <= WAIT_OBJECT_0 + num_all_events - 1)) {
508260
//woken up by event signalled
509261
/* is this due to a child process going down*/
510-
if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) {
262+
if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children))
511263
sigaddset(&pending_signals, W32_SIGCHLD);
512-
//errno = EINTR;
513-
//return -1;
514-
}
515264
}
516265
else if (ret == WAIT_IO_COMPLETION) {
517266
/* APC processed due to IO or signal*/

0 commit comments

Comments
 (0)