#fork and deterministic resumption of the resulting process

Andreas Raab andreas.raab at gmx.de
Mon Feb 4 21:04:13 UTC 2008


Hi -

In my never-ending quest for questionable behavior in multi-threaded 
situations just today I ran into a pattern which is dangerously common 
in our code. It basically goes like this:

MyClass>>startWorkerProcess
	"worker is an instance variable"
	worker:= [self runWorkerProcess] fork.

MyClass>>runWorkerProcess
	"Run the worker process"
	[Processor activeProcess == worker] whileTrue:[
		"...do the work..."
	].

MyClass>>stopWorkerProcess
	"Stop the worker process"
	worker := nil. "let it terminate itself"

Those of you who can immediately tell what the problem is should get a 
medal for an outstanding knack of analyzing concurrency problems ;-)

For the rest of us, the problem is that #fork in the above is not 
deterministic in the way that there is no guarantee whether the "worker" 
variable will be assigned when we enter the worker loop. It *would* be 
deterministic if the priority were below or above the current process' 
priority but when it's the same it can be affected by environmental 
effects (external signals, delay processing etc) leading to some very 
obscure runtime problems (in the above, the process would just not start).

To fix this problem I have changed BlockContext>>fork and 
BlockContext>>forkAt: to read, e.g.,

BlockContext>>fork
   "Create and schedule a Process running the code in the receiver."
   ^self forkAt: Processor activePriority

BlockContext>>forkAt: priority
   "Create and schedule a Process running the code in the receiver
   at the given priority. Answer the newly created process."
   | forkedProcess helperProcess |
   forkedProcess := self newProcess.
   forkedProcess priority: priority.
   priority = Processor activePriority ifTrue:[
     helperProcess := [forkedProcess resume] newProcess.
     helperProcess priority: priority-1.
     helperProcess resume.
   ] ifFalse:[
     forkedProcess resume
   ].
   ^forkedProcess

This will make sure that #fork has (for the purpose of resumption) the 
same semantics as forking at a lower priority has.

What do people think about this?

Cheers,
   - Andreas



More information about the Squeak-dev mailing list