@@ -43,24 +43,54 @@ static VOID CALLBACK
43
43
sigint_APCProc (
44
44
_In_ ULONG_PTR dwParam
45
45
) {
46
+ debug3 ("SIGINT APCProc()" );
46
47
sigaddset (& pending_signals , W32_SIGINT );
47
48
}
48
49
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 )
51
68
{
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 :
54
72
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;
55
86
}
56
87
}
57
88
58
89
void
59
90
sw_init_signal_handler_table () {
60
91
int i ;
61
92
62
- /* TODO SetConsoleCtrlHandler */
63
- //signal(SIGINT, native_sig_handler);
93
+ SetConsoleCtrlHandler (native_sig_handler , TRUE);
64
94
sigemptyset (& pending_signals );
65
95
/* this automatically sets all to SIG_DFL (0)*/
66
96
memset (sig_handlers , 0 , sizeof (sig_handlers ));
@@ -71,37 +101,96 @@ sw_init_signal_handler_table() {
71
101
struct _children {
72
102
HANDLE handles [MAX_CHILDREN ];
73
103
DWORD process_id [MAX_CHILDREN ];
104
+ /* total children */
74
105
DWORD num_children ;
106
+ /* #zombies */
107
+ /* (num_chileren - zombies) are live children */
108
+ DWORD num_zombies ;
75
109
} children ;
76
110
77
111
int
78
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 );
79
117
if (children .num_children == MAX_CHILDREN ) {
80
- errno = ENOTSUP ;
118
+ errno = ENOMEM ;
81
119
return -1 ;
82
120
}
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
+
85
135
children .num_children ++ ;
86
136
return 0 ;
87
137
}
88
138
89
139
int
90
140
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 ) ){
92
148
errno = EINVAL ;
93
149
return -1 ;
94
150
}
95
151
96
152
CloseHandle (children .handles [index ]);
97
- if (( children .num_children > 1 ) && ( index != ( children . num_children - 1 )) ) {
153
+ if (children .num_zombies == 0 ) {
98
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
+ }
99
172
}
100
173
101
174
children .num_children -- ;
102
175
return 0 ;
103
176
}
104
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
+
105
194
int
106
195
sw_remove_child (HANDLE child ) {
107
196
HANDLE * handles = children .handles ;
0 commit comments