#BUGFIX by cgexept.de
authorClaus Gittinger <cg@exept.de>
Sat, 16 Mar 2019 02:27:09 +0100
changeset 23928 2c38127d6863
parent 23927 3f82716744b9
child 23929 322b5ee4229b
#BUGFIX by cgexept.de class: Win32OperatingSystem class added: #terminateAllChildProcessesOf: changed: #terminateProcessGroup:
Win32OperatingSystem.st
--- a/Win32OperatingSystem.st	Sat Mar 16 00:51:37 2019 +0100
+++ b/Win32OperatingSystem.st	Sat Mar 16 02:27:09 2019 +0100
@@ -1092,6 +1092,7 @@
     "Modified: 7.1.1997 / 19:36:11 / stefan"
 ! !
 
+
 !Win32OperatingSystem class methodsFor:'OS signal constants'!
 
 sigABRT
@@ -7910,6 +7911,47 @@
     ^ self primitiveFailed
 !
 
+terminateAllChildProcessesOf:pid
+    "terminate all of a processes child processes.
+     This can be used to terminate processes started by a bridge,
+     especially leftover chromedrivers started by selenium"
+
+    |allProcesses toDo toTerminate someParentPid 
+     parentPerPid childrenPerPid alreadyIncluded|
+
+    allProcesses := self getAllProcesses.
+    parentPerPid := Dictionary new.
+    childrenPerPid := Dictionary new.
+    allProcesses do:[:each |
+        |eachPid eachParentPid|
+
+        eachPid := each pid.
+        eachParentPid := each parentPid.
+        parentPerPid at:eachPid put:eachParentPid.
+        (childrenPerPid at:eachParentPid ifAbsentPut:[Set new]) add:eachPid
+    ].
+
+    toTerminate := OrderedCollection new.
+    alreadyIncluded := Set new.
+
+    "/ generate toTerminate as a children-first list
+
+    toDo := OrderedCollection with:pid.
+    [toDo notEmpty] whileTrue:[
+        someParentPid := toDo removeFirst.
+        (childrenPerPid at:someParentPid ifAbsent:#()) do:[:eachChildPid |
+            (alreadyIncluded includes:eachChildPid) inform:[
+                toTerminate addFirst:eachChildPid.
+                alreadyIncluded add:eachChildPid.
+            ]
+        ].
+    ].
+
+    toTerminate do:[:eachPid |
+        self terminateProcess:eachPid
+    ].
+!
+
 terminateProcess:processHandleOrPid
     "terminate a process.
 
@@ -7956,19 +7998,21 @@
     "terminate a process group (that is all subprocesses of a process).
 
      ATTENTION WIN32:
-	 Under unix, we have terminateProcess, which does a soft
-	 terminate (giving the process a chance to cleanup) and
-	 killProcess, which does a hard terminate.
-	 Under WIN32, both (currently) use the TerminateProcess
-	 function, which unconditionally causes a process to exit.
-	 I.e. under WIN32, the process has no chance to perform cleanup.
-	 Use it only in extreme circumstances. The state of
-	 global data maintained by dynamic-link libraries (DLLs)
-	 may be compromised if TerminateProcess is used.
+         Under unix, we have terminateProcess, which does a soft
+         terminate (giving the process a chance to cleanup) and
+         killProcess, which does a hard terminate.
+         Under WIN32, both (currently) use the TerminateProcess
+         function, which unconditionally causes a process to exit.
+         I.e. under WIN32, the process has no chance to perform cleanup.
+         Use it only in extreme circumstances. The state of
+         global data maintained by dynamic-link libraries (DLLs)
+         may be compromised if TerminateProcess is used.
      TODO: send a WM_QUIT instead, to allow for proper shutdown."
 
     self killProcessGroup:processGroupHandleOrPid.
 
+    self terminateAllChildProcessesOf:processGroupHandleOrPid
+
     "Modified: / 03-08-2018 / 09:36:16 / Stefan Vogel"
 ! !
 
@@ -9380,48 +9424,7 @@
     "
 !
 
-xx_getAllProcessIds
-    "not needed - use getAllProcesses.
-     returns a collection of processID,
-     of all processes in the system"
-
-%{
-#if 0
-    OBJ pidArray;
-    DWORD *processes;
-    DWORD cbNeeded, nProcesses;
-    int i, moreNeeded = 1;
-    // Get the list of process identifiers.
-    int nProcSpace = 512;
-
-    while (moreNeeded) {
-	processes = (DWORD*)malloc(nProcSpace*sizeof(DWORD));
-	if (! EnumProcesses( processes, (nProcSpace*sizeof(DWORD)), &cbNeeded ) ) {
-	    goto failed;
-	}
-	moreNeeded = (cbNeeded == (nProcSpace*sizeof(DWORD)));
-	if (moreNeeded) {
-	    // returned exactly the size I gave it; maybe there are more
-	    nProcSpace *= 2;
-	    free (processes);
-	}
-    }
-    // Calculate how many process identifiers were returned.
-    nProcesses = cbNeeded / sizeof(DWORD);
-    pidArray = __ARRAY_NEW_INT(nProcesses);
-    if (pidArray != nil) {
-	for (i=0; i<nProcesses; i++) {
-	    __ArrayInstPtr(pidArray)->a_element[i] = __mkSmallInteger(processes[i]);
-	}
-	RETURN ( pidArray );
-    }
-failed: ;
-#endif
-%}.
-    self primitiveFailed.
-!
-
-    "
+"
      OperatingSystem getProcessId
     "
 getSystemID
@@ -10325,6 +10328,47 @@
      False is returned for UNIX, true for MSDOS and VMS"
 
     ^ true
+!
+
+xx_getAllProcessIds
+    "not needed - use getAllProcesses.
+     returns a collection of processID,
+     of all processes in the system"
+
+%{
+#if 0
+    OBJ pidArray;
+    DWORD *processes;
+    DWORD cbNeeded, nProcesses;
+    int i, moreNeeded = 1;
+    // Get the list of process identifiers.
+    int nProcSpace = 512;
+
+    while (moreNeeded) {
+	processes = (DWORD*)malloc(nProcSpace*sizeof(DWORD));
+	if (! EnumProcesses( processes, (nProcSpace*sizeof(DWORD)), &cbNeeded ) ) {
+	    goto failed;
+	}
+	moreNeeded = (cbNeeded == (nProcSpace*sizeof(DWORD)));
+	if (moreNeeded) {
+	    // returned exactly the size I gave it; maybe there are more
+	    nProcSpace *= 2;
+	    free (processes);
+	}
+    }
+    // Calculate how many process identifiers were returned.
+    nProcesses = cbNeeded / sizeof(DWORD);
+    pidArray = __ARRAY_NEW_INT(nProcesses);
+    if (pidArray != nil) {
+	for (i=0; i<nProcesses; i++) {
+	    __ArrayInstPtr(pidArray)->a_element[i] = __mkSmallInteger(processes[i]);
+	}
+	RETURN ( pidArray );
+    }
+failed: ;
+#endif
+%}.
+    self primitiveFailed.
 ! !
 
 !Win32OperatingSystem class methodsFor:'path queries'!