#BUGFIX by cgexept.de
class: Win32OperatingSystem class
added: #terminateAllChildProcessesOf:
changed: #terminateProcessGroup:
--- 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'!