#BUGFIX by stefan
class: ProcessorScheduler
changed:
#handleChildSignalInterrupt (send #blockingChildProcessWait instead of #isChildProcessWaitBlocking)
#monitor:action:
Fix race condition when more than a single subprocess is forked and
exitimg at a time.
--- a/ProcessorScheduler.st Thu Mar 29 13:05:39 2018 +0200
+++ b/ProcessorScheduler.st Thu Mar 29 16:21:22 2018 +0200
@@ -1175,7 +1175,8 @@
|osProcessStatus blocking wasBlocked|
- blocking := OperatingSystem isChildProcessWaitBlocking.
+ "/ blocking waits are no longer supported - see ProcessorScheduler>>#monitor:action:
+ blocking := OperatingSystem blockingChildProcessWait.
"/ no interrupt processing, to avoid races with monitorPid
wasBlocked := OperatingSystem blockInterrupts.
@@ -1213,9 +1214,9 @@
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
]
- "Modified: 5.1.1996 / 16:56:11 / stefan"
- "Modified: 28.2.1996 / 21:36:31 / cg"
- "Created: 12.4.1996 / 10:08:21 / stefan"
+ "Modified: / 28-02-1996 / 21:36:31 / cg"
+ "Created: / 12-04-1996 / 10:08:21 / stefan"
+ "Modified: / 29-03-2018 / 16:00:34 / stefan"
!
monitor:aBlockReturningPid action:actionBlock
@@ -1228,7 +1229,7 @@
status of the OS process changes (e.g. the process terminates).
The method returns the value from aBlockReturningPid (i.e. a pid or nil)."
- |pid wasBlocked exitStatus|
+ |pid waitedForactionBlock wasBlocked osProcessStatus|
"/ aBlock will be evaluated:
"/ on unix: as soon as a SIGCHLD interrupt for pid has been received.
@@ -1241,20 +1242,27 @@
pid notNil ifTrue:[
osChildExitActions at:pid put:actionBlock.
"check for a race, that SIGCHILD was received before we could register the actionBlock"
- exitStatus := OperatingSystem childProcessWait:false pid:pid.
- exitStatus notNil ifTrue:[
- self unmonitorPid:pid.
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- actionBlock value:exitStatus.
+ osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
+ osProcessStatus notNil ifTrue:[
+ "be careful, some implementations of #childProcessWait:pid:
+ (wait() and wait3() in very old unixes) wait for any pid!!"
+ osProcessStatus stillAlive ifTrue:[
+ waitedForactionBlock := osChildExitActions at:pid ifAbsent:nil.
+ ] ifFalse:[
+ waitedForactionBlock := osChildExitActions removeKey:pid ifAbsent:nil.
+ ].
+ waitedForactionBlock notNil ifTrue:[
+ waitedForactionBlock value:osProcessStatus
+ ].
].
].
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
^ pid
- "Created: / 25.3.1997 / 10:54:56 / stefan"
- "Modified: / 25.3.1997 / 11:21:05 / stefan"
- "Modified: / 15.4.1997 / 11:55:57 / David"
- "Modified: / 27.4.1999 / 20:09:38 / cg"
+ "Created: / 25-03-1997 / 10:54:56 / stefan"
+ "Modified: / 15-04-1997 / 11:55:57 / David"
+ "Modified: / 27-04-1999 / 20:09:38 / cg"
+ "Modified (format): / 29-03-2018 / 15:53:53 / stefan"
!
unmonitorPid:pid