You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2022/05/03 10:59:50 UTC

[commons-daemon] 01/03: Fix for https://issues.redhat.com/browse/JBCS-1261: Terminate child process that have been started by the service.

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-daemon.git

commit 85f98885db1686fb417aaba212758baf281e39e9
Author: Hudson <jb...@redhat.com>
AuthorDate: Thu Feb 17 10:15:27 2022 +0000

    Fix for https://issues.redhat.com/browse/JBCS-1261:
    Terminate child process that have been started by the service.
---
 src/native/windows/apps/prunsrv/prunsrv.c |  2 +
 src/native/windows/src/rprocess.c         | 83 ++++++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/src/native/windows/apps/prunsrv/prunsrv.c b/src/native/windows/apps/prunsrv/prunsrv.c
index 257c87b..4a1d976 100644
--- a/src/native/windows/apps/prunsrv/prunsrv.c
+++ b/src/native/windows/apps/prunsrv/prunsrv.c
@@ -1603,6 +1603,7 @@ void WINAPI service_ctrl_handler(DWORD dwCtrlCode)
         case SERVICE_CONTROL_SHUTDOWN:
             apxLogWrite(APXLOG_MARK_INFO "Service SHUTDOWN signalled.");
         case SERVICE_CONTROL_STOP:
+            apxLogWrite(APXLOG_MARK_INFO "Service SERVICE_CONTROL_STOP signalled.");
             if (SO_STOPTIMEOUT > 0) {
                 reportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, SO_STOPTIMEOUT * 1000);
             }
@@ -1617,6 +1618,7 @@ void WINAPI service_ctrl_handler(DWORD dwCtrlCode)
             CloseHandle(stopThread);
             return;
         case SERVICE_CONTROL_INTERROGATE:
+            apxLogWrite(APXLOG_MARK_INFO "Service SERVICE_CONTROL_INTERROGATE signalled.");
             reportServiceStatusE(APXLOG_LEVEL_TRACE,
                                 _service_status.dwCurrentState,
                                 _service_status.dwWin32ExitCode,
diff --git a/src/native/windows/src/rprocess.c b/src/native/windows/src/rprocess.c
index 27f223a..0cbeaa1 100644
--- a/src/native/windows/src/rprocess.c
+++ b/src/native/windows/src/rprocess.c
@@ -16,6 +16,7 @@
 
 #include "apxwin.h"
 #include "private.h"
+#include <tlhelp32.h>
 
 #define CHILD_RUNNING               0x0001
 #define CHILD_INITIALIZED           0x0002
@@ -299,6 +300,62 @@ cleanup:
 
     return rv;
 }
+/* Terminate child processes if any
+ * dwProcessId : the parent process
+ * dryrun : Don't kill, just list process in debug output file.
+ */
+static BOOL __apxProcessTerminateChild(DWORD dwProcessId, BOOL dryrun)
+{
+    HANDLE hProcessSnap;
+    PROCESSENTRY32 pe32;
+
+    apxLogWrite(APXLOG_MARK_DEBUG "TerminateChild 0x%08X (%d)", dwProcessId, dwProcessId );
+    // Take a snapshot of all processes in the system.
+    hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
+    if(hProcessSnap == INVALID_HANDLE_VALUE) {
+        apxLogWrite(APXLOG_MARK_DEBUG "CreateToolhelp32Snapshot (of processes) failed");
+        return(FALSE);
+    }
+
+    // Set the size of the structure before using it.
+    pe32.dwSize = sizeof(PROCESSENTRY32);
+
+    // Retrieve information about the first process,
+    // and return if unsuccessful
+    if( !Process32First(hProcessSnap, &pe32 )) {
+        apxLogWrite(APXLOG_MARK_DEBUG "Process32First failed");
+        CloseHandle(hProcessSnap);          // clean the snapshot object
+        return(FALSE);
+    }
+
+    // Now walk the snapshot of processes, and
+    // display information about each process in turn
+    do {
+        if (pe32.th32ParentProcessID == dwProcessId) {
+            apxLogWrite(APXLOG_MARK_DEBUG "PROCESS NAME:  %S", pe32.szExeFile);
+
+            apxLogWrite(APXLOG_MARK_DEBUG "Process ID        = 0x%08X", pe32.th32ProcessID);
+            apxLogWrite(APXLOG_MARK_DEBUG "Thread count      = %d",   pe32.cntThreads);
+            apxLogWrite(APXLOG_MARK_DEBUG "Parent process ID = 0x%08X", pe32.th32ParentProcessID);
+            apxLogWrite(APXLOG_MARK_DEBUG "Priority base     = %d", pe32.pcPriClassBase);
+            if (!dryrun) {
+                HANDLE hProcess;
+                hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
+                if(hProcess != NULL) {
+                   TerminateProcess(hProcess, CHILD_TERMINATE_CODE);
+                   apxLogWrite(APXLOG_MARK_DEBUG "Process ID: 0x%08X (%d) Terminated!", pe32.th32ProcessID, pe32.th32ProcessID);
+                   CloseHandle(hProcess);
+                } else {
+                   apxLogWrite(APXLOG_MARK_DEBUG "Process ID: 0x%08X (%d) Termination failed!", pe32.th32ProcessID, pe32.th32ProcessID);
+                }
+            }
+       }
+
+    } while(Process32Next(hProcessSnap, &pe32));
+  
+    CloseHandle(hProcessSnap);
+    return(TRUE);
+}
 
 /* Close the process.
  * Create the remote thread and call the ExitProcess
@@ -316,13 +373,16 @@ static BOOL __apxProcessClose(APXHANDLE hProcess)
     lpProc = APXHANDLE_DATA(hProcess);
     CHECK_IF_ACTIVE(lpProc);
 
+    __apxProcessTerminateChild(lpProc->stProcInfo.dwProcessId, TRUE);
     /* Try to close the child's stdin first */
     SAFE_CLOSE_HANDLE(lpProc->hChildInpWr);
     /* Wait 1 sec for child process to
      * recognize that the stdin has been closed.
      */
-    if (WaitForSingleObject(lpProc->stProcInfo.hProcess, 1000) == WAIT_OBJECT_0)
+    if (WaitForSingleObject(lpProc->stProcInfo.hProcess, 1000) == WAIT_OBJECT_0) {
+        apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose Gone(input)");
         goto cleanup;
+    }
 
     CHECK_IF_ACTIVE(lpProc);
 
@@ -345,18 +405,33 @@ static BOOL __apxProcessClose(APXHANDLE hProcess)
         if (!IS_INVALID_HANDLE(hRemote)) {
             if (WaitForSingleObject(lpProc->stProcInfo.hProcess,
                     2000) == WAIT_OBJECT_0) {
+                DWORD status;
+                if (!GetExitCodeProcess(lpProc->stProcInfo.hProcess, &status) ||
+                                (status != STILL_ACTIVE)) {
+                     apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose Gone(thread exit)");
+                     // We are here when the service starts something like wildfly via standalone.sh and wildfly doesn't terminate cleanly, 
+                     __apxProcessTerminateChild(lpProc->stProcInfo.dwProcessId, FALSE);
+                }
+
 
             }
             else {
+		apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose thread exit failed, terminate!");
                 TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
+                // __apxProcessTerminateChild ?
             }
             CloseHandle(hRemote);
-        }
+        } else {
+            apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose thread exit not usuable...");
+	}
         CloseHandle(hDup);
+        apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose Done?");
         goto cleanup;
     }
 
+    apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessClose terminate!");
     TerminateProcess(lpProc->stProcInfo.hProcess, CHILD_TERMINATE_CODE);
+    // __apxProcessTerminateChild ?
 
 cleanup:
      /* Close the process handle */
@@ -379,9 +454,11 @@ static BOOL __apxProcessCallback(APXHANDLE hObject, UINT uMsg,
         	/* Avoid processing the WM_CLOSE message multiple times */
         	if (lpProc->stProcInfo.hProcess == NULL) break;
             if (lpProc->dwChildStatus & CHILD_RUNNING) {
+                apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessCallback: CHILD_RUNNING");
                 __apxProcessClose(hObject);
                 /* Wait for all worker threads to exit */
                 WaitForMultipleObjects(3, lpProc->hWorkerThreads, TRUE, INFINITE);
+                apxLogWrite(APXLOG_MARK_DEBUG "__apxProcessCallback: CHILD_RUNNING DONE!");
             }
             SAFE_CLOSE_HANDLE(lpProc->stProcInfo.hProcess);
 
@@ -715,12 +792,14 @@ apxProcessWait(APXHANDLE hProcess, DWORD dwMilliseconds, BOOL bKill)
     if (hProcess->dwType != APXHANDLE_TYPE_PROCESS)
         return WAIT_ABANDONED;
 
+    apxLogWrite(APXLOG_MARK_DEBUG "apxProcessWait..");
     lpProc = APXHANDLE_DATA(hProcess);
 
     if (lpProc->dwChildStatus & CHILD_RUNNING) {
         DWORD rv = WaitForMultipleObjects(3, lpProc->hWorkerThreads,
                                           TRUE, dwMilliseconds);
         if (rv == WAIT_TIMEOUT && bKill) {
+            apxLogWrite(APXLOG_MARK_DEBUG "apxProcessWait.. killing???");
             __apxProcessCallback(hProcess, WM_CLOSE, 0, 0);
         }
         return rv;