You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mt...@apache.org on 2008/04/17 19:57:24 UTC

svn commit: r649208 - in /apr/apr/trunk: CHANGES include/apr.hw include/arch/win32/apr_arch_misc.h threadproc/win32/proc.c

Author: mturk
Date: Thu Apr 17 10:57:22 2008
New Revision: 649208

URL: http://svn.apache.org/viewvc?rev=649208&view=rev
Log:
mplement apr_proc_wait_all_procs for windows

Modified:
    apr/apr/trunk/CHANGES
    apr/apr/trunk/include/apr.hw
    apr/apr/trunk/include/arch/win32/apr_arch_misc.h
    apr/apr/trunk/threadproc/win32/proc.c

Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CHANGES?rev=649208&r1=649207&r2=649208&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES [utf-8] (original)
+++ apr/apr/trunk/CHANGES [utf-8] Thu Apr 17 10:57:22 2008
@@ -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

Modified: apr/apr/trunk/include/apr.hw
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr.hw?rev=649208&r1=649207&r2=649208&view=diff
==============================================================================
--- apr/apr/trunk/include/apr.hw (original)
+++ apr/apr/trunk/include/apr.hw Thu Apr 17 10:57:22 2008
@@ -100,6 +100,7 @@
 #include <winsock2.h>
 #include <mswsock.h>
 #include <ws2tcpip.h>
+#include <tlhelp32.h>
 #else
 #include <winsock.h>
 #endif

Modified: apr/apr/trunk/include/arch/win32/apr_arch_misc.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/win32/apr_arch_misc.h?rev=649208&r1=649207&r2=649208&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/win32/apr_arch_misc.h (original)
+++ apr/apr/trunk/include/arch/win32/apr_arch_misc.h Thu Apr 17 10:57:22 2008
@@ -404,6 +404,33 @@
     (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 */

Modified: apr/apr/trunk/threadproc/win32/proc.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/threadproc/win32/proc.c?rev=649208&r1=649207&r2=649208&view=diff
==============================================================================
--- apr/apr/trunk/threadproc/win32/proc.c (original)
+++ apr/apr/trunk/threadproc/win32/proc.c Thu Apr 17 10:57:22 2008
@@ -975,21 +975,6 @@
     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
@@ -1001,6 +986,132 @@
         return APR_PROC_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,