summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMladen Turk <mturk@apache.org>2008-04-17 17:57:22 +0000
committerMladen Turk <mturk@apache.org>2008-04-17 17:57:22 +0000
commitf0370b5c758780cb1f290be84bcfbbd5da869a28 (patch)
tree57918fc0bb257325663a7df01aaa756d8e364ad8
parent1c4ea398ffc0a52aa7c11bbbd549f1310283858b (diff)
downloadapr-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--CHANGES2
-rw-r--r--include/apr.hw1
-rw-r--r--include/arch/win32/apr_arch_misc.h27
-rw-r--r--threadproc/win32/proc.c141
4 files changed, 156 insertions, 15 deletions
diff --git a/CHANGES b/CHANGES
index 4765d8f03..150f67269 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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)