mirror of
https://github.com/PowerShell/Win32-OpenSSH.git
synced 2025-07-23 14:04:59 +02:00
SIGCHLD and waitpid implementation with sshd on board
This commit is contained in:
parent
ed535436d0
commit
77b0ec86df
@ -373,8 +373,7 @@ fileio_read(struct w32_io* pio, void *dst, unsigned int max) {
|
||||
}
|
||||
|
||||
/* pick up APC if IO has completed */
|
||||
if (-1 == wait_for_any_event(NULL, 0, 0))
|
||||
return -1;
|
||||
SleepEx(0, TRUE);
|
||||
|
||||
if (w32_io_is_blocking(pio)) {
|
||||
while (fileio_is_io_available(pio, TRUE) == FALSE) {
|
||||
@ -519,12 +518,7 @@ fileio_write(struct w32_io* pio, const void *buf, unsigned int max) {
|
||||
}
|
||||
}
|
||||
/* execute APC to give a chance for write to complete */
|
||||
else if (wait_for_any_event(NULL, 0, 0) == -1) {
|
||||
/* if interrupted but write has completed, we are good*/
|
||||
if ((errno != EINTR) || (pio->write_details.pending))
|
||||
return -1;
|
||||
errno = 0;
|
||||
}
|
||||
SleepEx(0, TRUE);
|
||||
|
||||
/* if write has completed, pick up any error reported*/
|
||||
if (!pio->write_details.pending && pio->write_details.error) {
|
||||
|
@ -70,4 +70,7 @@ typedef int sigset_t;
|
||||
|
||||
typedef unsigned short _mode_t;
|
||||
typedef _mode_t mode_t;
|
||||
typedef unsigned long pid_t;
|
||||
typedef int pid_t;
|
||||
|
||||
/* wait pid options */
|
||||
#define WNOHANG 1
|
@ -1,14 +1,17 @@
|
||||
#pragma once
|
||||
#include "..\w32posix.h"
|
||||
|
||||
#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
|
||||
#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
|
||||
#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
|
||||
#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
|
||||
#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
|
||||
#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
|
||||
//#define _W_INT(w) (*(int*)&(w)) /* convert union wait to int */
|
||||
//#define WIFEXITED(w) (!((_W_INT(w)) & 0377))
|
||||
//#define WIFSTOPPED(w) ((_W_INT(w)) & 0100)
|
||||
//#define WIFSIGNALED(w) (!WIFEXITED(w) && !WIFSTOPPED(w))
|
||||
//#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
|
||||
//#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
|
||||
|
||||
/* wait pid options */
|
||||
#define WNOHANG 1
|
||||
#define WIFEXITED(w) TRUE
|
||||
#define WIFSTOPPED(w) TRUE
|
||||
#define WIFSIGNALED(w) FALSE
|
||||
#define WEXITSTATUS(w) w
|
||||
#define WTERMSIG(w) -1
|
||||
|
||||
pid_t waitpid(pid_t pid, int *status, int options);
|
||||
int waitpid(int pid, int *status, int options);
|
@ -107,7 +107,7 @@ int w32_temp_DelChildToWatch(HANDLE processtowatch);
|
||||
int w32_temp_AddChildToWatch(HANDLE processtowatch);
|
||||
HANDLE w32_fd_to_handle(int fd);
|
||||
int w32_allocate_fd_for_handle(HANDLE h, BOOL is_sock);
|
||||
int sw_add_child(HANDLE child);
|
||||
int sw_add_child(HANDLE child, DWORD pid);
|
||||
|
||||
/* temporary definitions to aid in transition */
|
||||
#define WSHELPDelChildToWatch(a) w32_temp_DelChildToWatch((a))
|
||||
|
@ -8,11 +8,6 @@ int usleep(unsigned int useconds)
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid_t waitpid(pid_t pid, int *status, int options) {
|
||||
/* TODO - implement this*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
explicit_bzero(void *b, size_t len) {
|
||||
SecureZeroMemory(b, len);
|
||||
|
@ -70,17 +70,19 @@ sw_init_signal_handler_table() {
|
||||
#define MAX_CHILDREN 50
|
||||
struct _children {
|
||||
HANDLE handles[MAX_CHILDREN];
|
||||
//DWORD process_id[MAX_CHILDREN];
|
||||
DWORD process_id[MAX_CHILDREN];
|
||||
DWORD num_children;
|
||||
} children;
|
||||
|
||||
int
|
||||
sw_add_child(HANDLE child) {
|
||||
sw_add_child(HANDLE child, DWORD pid) {
|
||||
if (children.num_children == MAX_CHILDREN) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
children.handles[children.num_children++] = child;
|
||||
children.handles[children.num_children] = child;
|
||||
children.process_id[children.num_children] = pid;
|
||||
children.num_children++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -100,7 +102,6 @@ sw_remove_child_at_index(DWORD index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sw_remove_child(HANDLE child) {
|
||||
HANDLE* handles = children.handles;
|
||||
@ -117,6 +118,90 @@ sw_remove_child(HANDLE child) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int waitpid(int pid, int *status, int options) {
|
||||
DWORD index, ret, ret_id, exit_code, timeout = 0;
|
||||
HANDLE process = NULL;
|
||||
|
||||
if (options & (~WNOHANG)) {
|
||||
errno = ENOTSUP;
|
||||
DebugBreak();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pid < -1) || (pid == 0)) {
|
||||
errno = ENOTSUP;
|
||||
DebugBreak();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (children.num_children == 0) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pid > 0) {
|
||||
if (options != 0) {
|
||||
errno = ENOTSUP;
|
||||
DebugBreak();
|
||||
return -1;
|
||||
}
|
||||
/* find entry in table */
|
||||
for (index = 0; index < children.num_children; index++)
|
||||
if (children.process_id[index] == pid)
|
||||
break;
|
||||
|
||||
if (index == children.num_children) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
process = children.handles[index];
|
||||
ret = WaitForSingleObject(process, INFINITE);
|
||||
if (ret != WAIT_OBJECT_0)
|
||||
DebugBreak();//fatal
|
||||
|
||||
ret_id = children.process_id[index];
|
||||
GetExitCodeProcess(process, &exit_code);
|
||||
CloseHandle(process);
|
||||
sw_remove_child_at_index(index);
|
||||
if (status)
|
||||
*status = exit_code;
|
||||
return ret_id;
|
||||
}
|
||||
|
||||
/* pid = -1*/
|
||||
timeout = INFINITE;
|
||||
if (options & WNOHANG)
|
||||
timeout = 0;
|
||||
ret = WaitForMultipleObjects(children.num_children, children.handles, FALSE, timeout);
|
||||
if ((ret >= WAIT_OBJECT_0) && (ret < (WAIT_OBJECT_0 + children.num_children))) {
|
||||
index = ret - WAIT_OBJECT_0;
|
||||
process = children.handles[index];
|
||||
ret_id = children.process_id[index];
|
||||
GetExitCodeProcess(process, &exit_code);
|
||||
CloseHandle(process);
|
||||
sw_remove_child_at_index(index);
|
||||
if (status)
|
||||
*status = exit_code;
|
||||
return ret_id;
|
||||
}
|
||||
else if (ret == WAIT_TIMEOUT) {
|
||||
/* assert that WNOHANG was specified*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
DebugBreak();//fatal
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
sw_cleanup_child_zombies() {
|
||||
int pid = 1;
|
||||
while (pid > 0) {
|
||||
pid = waitpid(-1, NULL, WNOHANG);
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
HANDLE timer;
|
||||
ULONGLONG ticks_at_start; /* 0 if timer is not live */
|
||||
@ -223,7 +308,7 @@ sw_raise(int sig) {
|
||||
/* execute any default handlers */
|
||||
switch (sig) {
|
||||
case W32_SIGCHLD:
|
||||
/*TODO - execute sigchild default handler */
|
||||
sw_cleanup_child_zombies();
|
||||
break;
|
||||
case W32_SIGINT:
|
||||
/* TODO - execute sigint default handler */
|
||||
@ -274,9 +359,6 @@ sw_process_pending_signals() {
|
||||
sw_raise(exp[i]);
|
||||
sig_int = TRUE;
|
||||
}
|
||||
else {/* disposition is W32_SIG_IGN */
|
||||
/* TODO for SIG_CHLD - do clean up of Zombies */
|
||||
}
|
||||
|
||||
sigdelset(&pending_tmp, exp[i]);
|
||||
}
|
||||
@ -313,7 +395,9 @@ int
|
||||
wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
{
|
||||
HANDLE all_events[MAXIMUM_WAIT_OBJECTS];
|
||||
DWORD num_all_events = num_events + children.num_children;
|
||||
DWORD num_all_events;
|
||||
|
||||
num_all_events = num_events + children.num_children;
|
||||
|
||||
if (num_all_events > MAXIMUM_WAIT_OBJECTS) {
|
||||
errno = ENOTSUP;
|
||||
@ -335,11 +419,9 @@ wait_for_any_event(HANDLE* events, int num_events, DWORD milli_seconds)
|
||||
//woken up by event signalled
|
||||
/* is this due to a child process going down*/
|
||||
if (children.num_children && ((ret - WAIT_OBJECT_0) < children.num_children)) {
|
||||
/* TODO - enable this once all direct closes are removed in core code*/
|
||||
//sigaddset(&pending_signals, W32_SIGCHLD);
|
||||
//sw_remove_child(ret - WAIT_OBJECT_0);
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
sigaddset(&pending_signals, W32_SIGCHLD);
|
||||
//errno = EINTR;
|
||||
//return -1;
|
||||
}
|
||||
}
|
||||
else if (ret == WAIT_IO_COMPLETION) {
|
||||
|
@ -421,8 +421,7 @@ socketio_recv(struct w32_io* pio, void *buf, size_t len, int flags) {
|
||||
if (completed) {
|
||||
/* Let APC be scheduled */
|
||||
debug2("recv - Letting APC to execute, io:%p", pio);
|
||||
if (wait_for_any_event(NULL, 0, 0) == -1)
|
||||
return -1;
|
||||
SleepEx(0, TRUE);
|
||||
if (pio->read_details.pending) {
|
||||
/* this shouldn't be happening */
|
||||
errno = EOTHER;
|
||||
@ -588,13 +587,7 @@ socketio_send(struct w32_io* pio, const void *buf, size_t len, int flags) {
|
||||
debug2("send - WSASend() returned 0, APC scheduled io:%p", pio);
|
||||
pio->write_details.pending = TRUE;
|
||||
pio->write_details.remaining = wsabuf.len;
|
||||
if (wait_for_any_event(NULL, 0, 0) == -1) {
|
||||
//interrupted but send went through
|
||||
if (errno == EINTR)
|
||||
errno = 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
SleepEx(0, TRUE);
|
||||
if ((pio->write_details.pending) || (pio->write_details.remaining != 0)) {
|
||||
errno = EOTHER;
|
||||
debug("send - ERROR: Unexpected IO state, io:%p", pio);
|
||||
|
@ -123,7 +123,7 @@ int termio_close(struct w32_io* pio);
|
||||
|
||||
/* signal related APIs*/
|
||||
int sw_initialize();
|
||||
int sw_add_child(HANDLE child);
|
||||
int sw_add_child(HANDLE child, DWORD pid);
|
||||
int sw_remove_child(HANDLE child);
|
||||
unsigned int sw_alarm(unsigned int seconds);
|
||||
sighandler_t sw_signal(int signum, sighandler_t handler);
|
||||
|
25
session.c
25
session.c
@ -843,9 +843,8 @@ do_exec_no_pty(Session *s, const char *command)
|
||||
* Log the process handle (fake it as the pid) for termination lookups
|
||||
*/
|
||||
|
||||
s -> pid = pi.hProcess;
|
||||
s -> processId = pi.dwProcessId;
|
||||
sw_add_child(pi.hProcess);
|
||||
s -> pid = pi.dwProcessId;
|
||||
sw_add_child(pi.hProcess, pi.dwProcessId);
|
||||
|
||||
// Add the child process created to select mux so that during our select data call we know if the process has exited
|
||||
/* TODO - fix thi s*/
|
||||
@ -2877,10 +2876,12 @@ session_pty_cleanup2(Session *s)
|
||||
|
||||
debug("Sending exit signal to child process [pid = %u]...", s -> pid);
|
||||
|
||||
if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
|
||||
{
|
||||
debug("ERROR. Cannot send signal to process.");
|
||||
}
|
||||
//if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
|
||||
//{
|
||||
// debug("ERROR. Cannot send signal to process.");
|
||||
//}
|
||||
|
||||
kill(s->pid, SIGTERM);
|
||||
|
||||
/*
|
||||
* Try wait 100 ms until child finished.
|
||||
@ -2991,11 +2992,11 @@ session_close_single_x11(int id, void *arg)
|
||||
{
|
||||
debug("Sending exit signal to child process [pid = %u]...", s -> pid);
|
||||
|
||||
if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
|
||||
{
|
||||
debug("ERROR. Cannot send signal to process.");
|
||||
}
|
||||
|
||||
//if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, s -> processId))
|
||||
//{
|
||||
// debug("ERROR. Cannot send signal to process.");
|
||||
//}
|
||||
kill(s->pid, SIGTERM);
|
||||
/*
|
||||
* Try wait 100 ms until child finished.
|
||||
*/
|
||||
|
@ -35,10 +35,6 @@ struct Session {
|
||||
struct passwd *pw;
|
||||
Authctxt *authctxt;
|
||||
pid_t pid;
|
||||
|
||||
#ifdef WIN32_FIXME
|
||||
DWORD processId;
|
||||
#endif
|
||||
|
||||
/* tty */
|
||||
char *term;
|
||||
|
12
sshd.c
12
sshd.c
@ -1605,20 +1605,16 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
||||
&si, &pi) == FALSE) {
|
||||
debug("CreateProcess failure: %d", GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close child thread and process handles so it can go away
|
||||
*/
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
|
||||
close(*newsock);
|
||||
close(startup_pipes[i]);
|
||||
startup_pipes[i] = -1;
|
||||
startups--;
|
||||
|
||||
sw_add_child(pi.hProcess, pi.dwProcessId);
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
pid = pi.dwProcessId;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user