Skip to content

Commit 327f077

Browse files
committed
Adding zombie state to SIGCHLD implementaion
1 parent 77b0ec8 commit 327f077

File tree

1 file changed

+100
-11
lines changed

1 file changed

+100
-11
lines changed

contrib/win32/win32compat/signal.c

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,54 @@ static VOID CALLBACK
4343
sigint_APCProc(
4444
_In_ ULONG_PTR dwParam
4545
) {
46+
debug3("SIGINT APCProc()");
4647
sigaddset(&pending_signals, W32_SIGINT);
4748
}
4849

49-
static void
50-
native_sig_handler(int signal)
50+
static VOID CALLBACK
51+
sigterm_APCProc(
52+
_In_ ULONG_PTR dwParam
53+
) {
54+
debug3("SIGTERM APCProc()");
55+
sigaddset(&pending_signals, W32_SIGTERM);
56+
}
57+
58+
static VOID CALLBACK
59+
sigtstp_APCProc(
60+
_In_ ULONG_PTR dwParam
61+
) {
62+
debug3("SIGTSTP APCProc()");
63+
sigaddset(&pending_signals, W32_SIGTSTP);
64+
}
65+
66+
static BOOL WINAPI
67+
native_sig_handler(DWORD dwCtrlType)
5168
{
52-
if (signal == SIGINT) {
53-
/* Queue signint APC */
69+
debug("Native Ctrl+C handler, CtrlType %d", dwCtrlType);
70+
switch (dwCtrlType) {
71+
case CTRL_C_EVENT:
5472
QueueUserAPC(sigint_APCProc, main_thread, (ULONG_PTR)NULL);
73+
return TRUE;
74+
case CTRL_BREAK_EVENT:
75+
QueueUserAPC(sigtstp_APCProc, main_thread, (ULONG_PTR)NULL);
76+
return TRUE;
77+
case CTRL_CLOSE_EVENT:
78+
case CTRL_LOGOFF_EVENT:
79+
case CTRL_SHUTDOWN_EVENT:
80+
QueueUserAPC(sigterm_APCProc, main_thread, (ULONG_PTR)NULL);
81+
/* wait for main thread to terminate */
82+
WaitForSingleObject(main_thread, INFINITE);
83+
return TRUE;
84+
default:
85+
return FALSE;
5586
}
5687
}
5788

5889
void
5990
sw_init_signal_handler_table() {
6091
int i;
6192

62-
/* TODO SetConsoleCtrlHandler */
63-
//signal(SIGINT, native_sig_handler);
93+
SetConsoleCtrlHandler(native_sig_handler, TRUE);
6494
sigemptyset(&pending_signals);
6595
/* this automatically sets all to SIG_DFL (0)*/
6696
memset(sig_handlers, 0, sizeof(sig_handlers));
@@ -71,37 +101,96 @@ sw_init_signal_handler_table() {
71101
struct _children {
72102
HANDLE handles[MAX_CHILDREN];
73103
DWORD process_id[MAX_CHILDREN];
104+
/* total children */
74105
DWORD num_children;
106+
/* #zombies */
107+
/* (num_chileren - zombies) are live children */
108+
DWORD num_zombies;
75109
} children;
76110

77111
int
78112
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);
79117
if (children.num_children == MAX_CHILDREN) {
80-
errno = ENOTSUP;
118+
errno = ENOMEM;
81119
return -1;
82120
}
83-
children.handles[children.num_children] = child;
84-
children.process_id[children.num_children] = pid;
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+
85135
children.num_children++;
86136
return 0;
87137
}
88138

89139
int
90140
sw_remove_child_at_index(DWORD index) {
91-
if (index >= children.num_children) {
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) ){
92148
errno = EINVAL;
93149
return -1;
94150
}
95151

96152
CloseHandle(children.handles[index]);
97-
if ((children.num_children > 1) && (index != (children.num_children - 1))) {
153+
if (children.num_zombies == 0) {
98154
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+
}
99172
}
100173

101174
children.num_children--;
102175
return 0;
103176
}
104177

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+
105194
int
106195
sw_remove_child(HANDLE child) {
107196
HANDLE* handles = children.handles;

0 commit comments

Comments
 (0)