Hello guys, Yesterday I had this problem that at startup a pharo image has several process running at priority 40. The problem is that my tests (run from command line) trigger #valueWithin:onTimeout: and the protected block (the block calling #valueWithin:onTimeout:) would always timed out for the first test as resuming the watchdog in #valueWithin:onTimeout: allows another runnable process at the same priority as the active process to be run.
Example: Here we have two process at the activePriority, the second process takes 100ms to be run and as the transcript shows, the protected block always times out because this other process is started after the watchdog so during the protected block activation. | p endTime | p := Processor activeProcess priority. [ 'Process2Start' logCr. endTime := Time millisecondClockValue + 100. [ Time millisecondClockValue > endTime ] whileFalse: [ 1 + 2 + 3 ]. 'Process2End' logCr. ] forkAt: p. [ 'protected' logCr] valueWithin: 0.05 second onTimeout: [ 'timeout' logCr ]. Transcript displays: 'Process2Start' 'Process2End' 'timeout' I'm not very familiar with Pharo's process framework nor with processes in general so I would like to discuss the problem. *Question 1: Is it a bug ?* I fixed it by adding a Processor yield just before resuming the watchdog in #valueWithin:onTimeout: to allow other runnable process at the activePriority to be run before the protected block and therefore forbidding other process started outside of the protected block to trigger the time out. No process can be started in between the Processor yield and watchdog resume. *Question 2: Can someone tell me if this code looks ok ? I've just added Processor yield.* valueWithin: aDuration onTimeout: timeoutBlock "Evaluate the receiver. If the evaluation does not complete in less than aDuration evaluate the timeoutBlock instead" | theProcess delay watchdog tag | aDuration <= Duration zero ifTrue: [^ timeoutBlock value ]. "the block will be executed in the current process" theProcess := Processor activeProcess. delay := aDuration asDelay. tag := self. "make a watchdog process" watchdog := [ delay wait. "wait for timeout or completion" theProcess ifNotNil:[ theProcess signalException: (TimedOut new tag: tag)] ] newProcess. "Watchdog needs to run at high priority to do its job (but not at timing priority)" watchdog priority: Processor timingPriority-1. *Processor yield.* "catch the timeout signal" ^ [ watchdog resume. "start up the watchdog" self ensure:[ "evaluate the receiver" theProcess := nil. "it has completed, so ..." delay delaySemaphore signal. "arrange for the watchdog to exit" ]] on: TimedOut do: [ :e | e tag == tag ifTrue:[ timeoutBlock value ] ifFalse:[ e pass]].
