Skip to content

Commit 77b0ec8

Browse files
committed
SIGCHLD and waitpid implementation with sshd on board
1 parent ed53543 commit 77b0ec8

File tree

11 files changed

+135
-72
lines changed

11 files changed

+135
-72
lines changed

contrib/win32/win32compat/fileio.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
373373
}
374374

375375
/* pick up APC if IO has completed */
376-
if (-1 == wait_for_any_event(NULL, 0, 0))
377-
return -1;
376+
SleepEx(0, TRUE);
378377

379378
if (w32_io_is_blocking(pio)) {
380379
while (fileio_is_io_available(pio, TRUE) == FALSE) {
@@ -519,12 +518,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
519518
}
520519
}
521520
/* execute APC to give a chance for write to complete */
522-
else if (wait_for_any_event(NULL, 0, 0) == -1) {
523-
/* if interrupted but write has completed, we are good*/
524-
if ((errno != EINTR) || (pio->write_details.pending))
525-
return -1;
526-
errno = 0;
527-
}
521+
SleepEx(0, TRUE);
528522

529523
/* if write has completed, pick up any error reported*/
530524
if (!pio->write_details.pending && pio->write_details.error) {

contrib/win32/win32compat/inc/defs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,7 @@ typedef int sigset_t;
7070

7171
typedef unsigned short _mode_t;
7272
typedef _mode_t mode_t;
73-
typedef unsigned long pid_t;
73+
typedef int pid_t;
74+
75+
/* wait pid options */
76+
#define WNOHANG 1
Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
#pragma once
22
#include "..\w32posix.h"
33

4-
#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
5-
#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
6-
#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
7-
#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
8-
#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
9-
#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
4+
//#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
5+
//#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
6+
//#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
7+
//#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
8+
//#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
9+
//#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
1010

11-
/* wait pid options */
12-
#define WNOHANG 1
11+
#define WIFEXITED(w) TRUE
12+
#define WIFSTOPPED(w) TRUE
13+
#define WIFSIGNALED(w) FALSE
14+
#define WEXITSTATUS(w) w
15+
#define WTERMSIG(w) -1
1316

14-
pid_t waitpid(pid_t pid, int *status, int options);
17+
int waitpid(int pid, int *status, int options);

contrib/win32/win32compat/inc/w32posix.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ int w32_temp_DelChildToWatch(HANDLE processtowatch);
107107
int w32_temp_AddChildToWatch(HANDLE processtowatch);
108108
HANDLE w32_fd_to_handle(int fd);
109109
int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock);
110-
int sw_add_child(HANDLE child);
110+
int sw_add_child(HANDLE child, DWORD pid);
111111

112112
/* temporary definitions to aid in transition */
113113
#define WSHELPDelChildToWatch(a) w32_temp_DelChildToWatch((a))

contrib/win32/win32compat/misc.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ int usleep(unsigned int useconds)
88
return 1;
99
}
1010

11-
pid_t waitpid(pid_t pid, int *status, int options) {
12-
/* TODO - implement this*/
13-
return 0;
14-
}
15-
1611
void
1712
explicit_bzero(void *b, size_t len) {
1813
SecureZeroMemory(b, len);

contrib/win32/win32compat/signal.c

Lines changed: 96 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,19 @@ sw_init_signal_handler_table() {
7070
#define MAX_CHILDREN 50
7171
struct _children {
7272
HANDLE handles[MAX_CHILDREN];
73-
//DWORD process_id[MAX_CHILDREN];
73+
DWORD process_id[MAX_CHILDREN];
7474
DWORD num_children;
7575
} children;
7676

7777
int
78-
sw_add_child(HANDLE child) {
78+
sw_add_child(HANDLE child, DWORD pid) {
7979
if (children.num_children == MAX_CHILDREN) {
8080
errno = ENOTSUP;
8181
return -1;
8282
}
83-
children.handles[children.num_children++] = child;
83+
children.handles[children.num_children] = child;
84+
children.process_id[children.num_children] = pid;
85+
children.num_children++;
8486
return 0;
8587
}
8688

@@ -100,7 +102,6 @@ sw_remove_child_at_index(DWORD index) {
100102
return 0;
101103
}
102104

103-
104105
int
105106
sw_remove_child(HANDLE child) {
106107
HANDLE* handles = children.handles;
@@ -117,6 +118,90 @@ sw_remove_child(HANDLE child) {
117118
return -1;
118119
}
119120

121+
int waitpid(int pid, int *status, int options) {
122+
DWORD index, ret, ret_id, exit_code, timeout = 0;
123+
HANDLE process = NULL;
124+
125+
if (options & (~WNOHANG)) {
126+
errno = ENOTSUP;
127+
DebugBreak();
128+
return -1;
129+
}
130+
131+
if ((pid < -1) || (pid == 0)) {
132+
errno = ENOTSUP;
133+
DebugBreak();
134+
return -1;
135+
}
136+
137+
if (children.num_children == 0) {
138+
errno = ECHILD;
139+
return -1;
140+
}
141+
142+
if (pid > 0) {
143+
if (options != 0) {
144+
errno = ENOTSUP;
145+
DebugBreak();
146+
return -1;
147+
}
148+
/* find entry in table */
149+
for (index = 0; index < children.num_children; index++)
150+
if (children.process_id[index] == pid)
151+
break;
152+
153+
if (index == children.num_children) {
154+
errno = ECHILD;
155+
return -1;
156+
}
157+
158+
process = children.handles[index];
159+
ret = WaitForSingleObject(process, INFINITE);
160+
if (ret != WAIT_OBJECT_0)
161+
DebugBreak();//fatal
162+
163+
ret_id = children.process_id[index];
164+
GetExitCodeProcess(process, &exit_code);
165+
CloseHandle(process);
166+
sw_remove_child_at_index(index);
167+
if (status)
168+
*status = exit_code;
169+
return ret_id;
170+
}
171+
172+
/* pid = -1*/
173+
timeout = INFINITE;
174+
if (options & WNOHANG)
175+
timeout = 0;
176+
ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
177+
if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
178+
index = ret - WAIT_OBJECT_0;
179+
process = children.handles[index];
180+
ret_id = children.process_id[index];
181+
GetExitCodeProcess(process, &exit_code);
182+
CloseHandle(process);
183+
sw_remove_child_at_index(index);
184+
if (status)
185+
*status = exit_code;
186+
return ret_id;
187+
}
188+
else if (ret == WAIT_TIMEOUT) {
189+
/* assert that WNOHANG was specified*/
190+
return 0;
191+
}
192+
193+
DebugBreak();//fatal
194+
return -1;
195+
}
196+
197+
static void
198+
sw_cleanup_child_zombies() {
199+
int pid = 1;
200+
while (pid > 0) {
201+
pid = waitpid(-1, NULL, WNOHANG);
202+
}
203+
}
204+
120205
struct {
121206
HANDLE timer;
122207
ULONGLONG ticks_at_start; /* 0 if timer is not live */
@@ -223,7 +308,7 @@ sw_raise(int sig) {
223308
/* execute any default handlers */
224309
switch (sig) {
225310
case W32_SIGCHLD:
226-
/*TODO - execute sigchild default handler */
311+
sw_cleanup_child_zombies();
227312
break;
228313
case W32_SIGINT:
229314
/* TODO - execute sigint default handler */
@@ -274,9 +359,6 @@ sw_process_pending_signals() {
274359
sw_raise(exp[i]);
275360
sig_int = TRUE;
276361
}
277-
else {/* disposition is W32_SIG_IGN */
278-
/* TODO for SIG_CHLD - do clean up of Zombies */
279-
}
280362

281363
sigdelset(&pending_tmp, exp[i]);
282364
}
@@ -313,7 +395,9 @@ int
313395
wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
314396
{
315397
HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
316-
DWORD num_all_events = num_events + children.num_children;
398+
DWORD num_all_events;
399+
400+
num_all_events = num_events + children.num_children;
317401

318402
if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
319403
errno = ENOTSUP;
@@ -335,11 +419,9 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
335419
//woken up by event signalled
336420
/* is this due to a child process going down*/
337421
if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) {
338-
/* TODO - enable this once all direct closes are removed in core code*/
339-
//sigaddset(&pending_signals, W32_SIGCHLD);
340-
//sw_remove_child(ret - WAIT_OBJECT_0);
341-
errno = EINTR;
342-
return -1;
422+
sigaddset(&pending_signals, W32_SIGCHLD);
423+
//errno = EINTR;
424+
//return -1;
343425
}
344426
}
345427
else if (ret == WAIT_IO_COMPLETION) {

contrib/win32/win32compat/socketio.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
421421
if (completed) {
422422
/* Let APC be scheduled */
423423
debug2("recv - Letting APC to execute, io:%p", pio);
424-
if (wait_for_any_event(NULL, 0, 0) == -1)
425-
return -1;
424+
SleepEx(0, TRUE);
426425
if (pio->read_details.pending) {
427426
/* this shouldn't be happening */
428427
errno = EOTHER;
@@ -588,13 +587,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
588587
debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
589588
pio->write_details.pending = TRUE;
590589
pio->write_details.remaining = wsabuf.len;
591-
if (wait_for_any_event(NULL, 0, 0) == -1) {
592-
//interrupted but send went through
593-
if (errno == EINTR)
594-
errno = 0;
595-
else
596-
return -1;
597-
}
590+
SleepEx(0, TRUE);
598591
if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
599592
errno = EOTHER;
600593
debug("send - ERROR: Unexpected IO state, io:%p", pio);

contrib/win32/win32compat/w32fd.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ int termio_close(struct w32_io* pio);
123123

124124
/* signal related APIs*/
125125
int sw_initialize();
126-
int sw_add_child(HANDLE child);
126+
int sw_add_child(HANDLE child, DWORD pid);
127127
int sw_remove_child(HANDLE child);
128128
unsigned int sw_alarm(unsigned int seconds);
129129
sighandler_t sw_signal(int signum, sighandler_t handler);

session.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -843,9 +843,8 @@ do_exec_no_pty(Session *s, const char *command)
843843
* Log the process handle (fake it as the pid) for termination lookups
844844
*/
845845

846-
s -> pid = pi.hProcess;
847-
s -> processId = pi.dwProcessId;
848-
sw_add_child(pi.hProcess);
846+
s -> pid = pi.dwProcessId;
847+
sw_add_child(pi.hProcess, pi.dwProcessId);
849848

850849
// Add the child process created to select mux so that during our select data call we know if the process has exited
851850
/* TODO - fix thi s*/
@@ -2877,10 +2876,12 @@ session_pty_cleanup2(Session *s)
28772876

28782877
debug("Sending exit signal to child process [pid = %u]...", s -> pid);
28792878

2880-
if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
2881-
{
2882-
debug("ERROR. Cannot send signal to process.");
2883-
}
2879+
//if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
2880+
//{
2881+
// debug("ERROR. Cannot send signal to process.");
2882+
//}
2883+
2884+
kill(s->pid, SIGTERM);
28842885

28852886
/*
28862887
* Try wait 100 ms until child finished.
@@ -2991,11 +2992,11 @@ session_close_single_x11(int id, void *arg)
29912992
{
29922993
debug("Sending exit signal to child process [pid = %u]...", s -> pid);
29932994

2994-
if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
2995-
{
2996-
debug("ERROR. Cannot send signal to process.");
2997-
}
2998-
2995+
//if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
2996+
//{
2997+
// debug("ERROR. Cannot send signal to process.");
2998+
//}
2999+
kill(s->pid, SIGTERM);
29993000
/*
30003001
* Try wait 100 ms until child finished.
30013002
*/

session.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ struct Session {
3535
struct passwd *pw;
3636
Authctxt *authctxt;
3737
pid_t pid;
38-
39-
#ifdef WIN32_FIXME
40-
DWORD processId;
41-
#endif
4238

4339
/* tty */
4440
char *term;

0 commit comments

Comments
 (0)