diff options
author | Mladen Turk <mturk@apache.org> | 2008-04-17 17:57:22 +0000 |
---|---|---|
committer | Mladen Turk <mturk@apache.org> | 2008-04-17 17:57:22 +0000 |
commit | f0370b5c758780cb1f290be84bcfbbd5da869a28 (patch) | |
tree | 57918fc0bb257325663a7df01aaa756d8e364ad8 | |
parent | 1c4ea398ffc0a52aa7c11bbbd549f1310283858b (diff) | |
download | apr-f0370b5c758780cb1f290be84bcfbbd5da869a28.tar.gz |
mplement apr_proc_wait_all_procs for windows
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@649208 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | include/apr.hw | 1 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_misc.h | 27 | ||||
-rw-r--r-- | threadproc/win32/proc.c | 141 |
4 files changed, 156 insertions, 15 deletions
@@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes for APR 1.4.0 + *) Implement apr_proc_wait_all_procs for windows. + [Mladen Turk] Changes for APR 1.3.0 diff --git a/include/apr.hw b/include/apr.hw index 8d7431941..c1e2e51ee 100644 --- a/include/apr.hw +++ b/include/apr.hw @@ -100,6 +100,7 @@ #include <winsock2.h> #include <mswsock.h> #include <ws2tcpip.h> +#include <tlhelp32.h> #else #include <winsock.h> #endif diff --git a/include/arch/win32/apr_arch_misc.h b/include/arch/win32/apr_arch_misc.h index e4beec27b..76076da34 100644 --- a/include/arch/win32/apr_arch_misc.h +++ b/include/arch/win32/apr_arch_misc.h @@ -404,6 +404,33 @@ APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, LONG, WINAPI, ZwQueryInformationFile, 0, ( (hObject, pIOSB, pFI, LenFI, info)); #define ZwQueryInformationFile apr_winapi_ZwQueryInformationFile +#ifdef CreateToolhelp32Snapshot +#undef CreateToolhelp32Snapshot +#endif +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, HANDLE, WINAPI, CreateToolhelp32Snapshot, 0, ( + DWORD dwFlags, + DWORD th32ProcessID), + (dwFlags, th32ProcessID)); +#define CreateToolhelp32Snapshot apr_winapi_CreateToolhelp32Snapshot + +#ifdef Process32FirstW +#undef Process32FirstW +#endif +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, Process32FirstW, 0, ( + HANDLE hSnapshot, + LPPROCESSENTRY32W lppe), + (hSnapshot, lppe)); +#define Process32FirstW apr_winapi_Process32FirstW + +#ifdef Process32NextW +#undef Process32NextW +#endif +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, Process32NextW, 0, ( + HANDLE hSnapshot, + LPPROCESSENTRY32W lppe), + (hSnapshot, lppe)); +#define Process32NextW apr_winapi_Process32NextW + #endif /* !defined(_WIN32_WCE) */ #endif /* ! MISC_H */ diff --git a/threadproc/win32/proc.c b/threadproc/win32/proc.c index 2c7dcabc8..79a2fd167 100644 --- a/threadproc/win32/proc.c +++ b/threadproc/win32/proc.c @@ -975,21 +975,6 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, - int *exitcode, - apr_exit_why_e *exitwhy, - apr_wait_how_e waithow, - apr_pool_t *p) -{ - /* Unix does apr_proc_wait(proc(-1), exitcode, exitwhy, waithow) - * but Win32's apr_proc_wait won't work that way. We can either - * register all APR created processes in some sort of AsyncWait - * thread, or simply walk from the global process pool for all - * apr_pool_note_subprocess()es registered with APR. - */ - return APR_ENOTIMPL; -} - static apr_exit_why_e why_from_exit_code(DWORD exit) { /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how * this class of failures was determined @@ -1003,6 +988,132 @@ static apr_exit_why_e why_from_exit_code(DWORD exit) { /* ### No way to tell if Dr Watson grabbed a core, AFAICT. */ } +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ +#if APR_HAS_UNICODE_FS +#ifndef _WIN32_WCE + IF_WIN_OS_IS_UNICODE + { + DWORD dwId = GetCurrentProcessId(); + DWORD i; + DWORD nChilds = 0; + DWORD nActive = 0; + HANDLE ps32; + PROCESSENTRY32W pe32; + BOOL bHasMore = FALSE; + DWORD dwFlags = PROCESS_QUERY_INFORMATION; + apr_status_t rv = APR_EGENERAL; + + if (waithow == APR_WAIT) + dwFlags |= SYNCHRONIZE; + if (!(ps32 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) { + return apr_get_os_error(); + } + pe32.dwSize = sizeof(PROCESSENTRY32W); + if (!Process32FirstW(ps32, &pe32)) { + if (GetLastError() == ERROR_NO_MORE_FILES) + return APR_EOF; + else + return apr_get_os_error(); + } + do { + DWORD dwRetval = 0; + DWORD nHandles = 0; + HANDLE hProcess = NULL; + HANDLE pHandles[MAXIMUM_WAIT_OBJECTS]; + do { + if (pe32.th32ParentProcessID == dwId) { + nChilds++; + if ((hProcess = OpenProcess(dwFlags, FALSE, + pe32.th32ProcessID)) != NULL) { + if (GetExitCodeProcess(hProcess, &dwRetval)) { + if (dwRetval == STILL_ACTIVE) { + nActive++; + if (waithow == APR_WAIT) + pHandles[nHandles++] = hProcess; + else + CloseHandle(hProcess); + } + else { + /* Process has exited. + * No need to wait for its termination. + */ + CloseHandle(hProcess); + if (exitcode) + *exitcode = dwRetval; + if (exitwhy) + *exitwhy = why_from_exit_code(dwRetval); + proc->pid = pe32.th32ProcessID; + } + } + else { + /* Unexpected error code. + * Cleanup and return; + */ + rv = apr_get_os_error(); + CloseHandle(hProcess); + for (i = 0; i < nHandles; i++) + CloseHandle(pHandles[i]); + return rv; + } + } + else { + /* This is our child, so it shouldn't happen + * that we cannot open our child's process handle. + * However if the child process increased the + * security token it might fail. + */ + } + } + } while ((bHasMore = Process32NextW(ps32, &pe32)) && + nHandles < MAXIMUM_WAIT_OBJECTS); + if (nHandles) { + /* Wait for all collected processes to finish */ + DWORD waitStatus = WaitForMultipleObjects(nHandles, pHandles, + TRUE, INFINITE); + for (i = 0; i < nHandles; i++) + CloseHandle(pHandles[i]); + if (waitStatus == WAIT_OBJECT_0) { + /* Decrease active count by the number of awaited + * processes. + */ + nActive -= nHandles; + } + else { + /* Broken from the infinite loop */ + break; + } + } + } while (bHasMore); + CloseHandle(ps32); + if (waithow != APR_WAIT) { + if (nChilds && nChilds == nActive) { + /* All child processes are running */ + rv = APR_CHILD_NOTDONE; + proc->pid = -1; + } + else { + /* proc->pid contains the pid of the + * exited processes + */ + rv = APR_CHILD_DONE; + } + } + if (nActive == 0) { + rv = APR_CHILD_DONE; + proc->pid = -1; + } + return rv; + } +#endif /* _WIN32_WCE */ +#endif /* APR_HAS_UNICODE_FS */ + return APR_ENOTIMPL; +} + APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, int *exitcode, apr_exit_why_e *exitwhy, apr_wait_how_e waithow) |