[squeak-dev] OSProcess and Cuis [Diagnosed]
Juan Vuletich
juan at jvuletich.org
Fri Sep 3 13:07:53 UTC 2010
On 02/09/2010 06:48 p.m., Ross Boylan wrote:
> On Thu, 2010-09-02 at 14:20 -0700, Ross Boylan wrote:
>> I'm getting errors trying to file OSProcess (the st file from
>> OSProcess-dtl.56.mcz) into Cuis. I am trying to do this so I can run
>> magma tests.
>>
>> I don't know if there's any chance of this working. In the image
>> Smalltalk listBuiltinModules #('ExuperyPlugin 27 February 2009 (i)')
>> Smalltalk listLoadedModules. #('UnixOSProcessPlugin 27 February 2009 (e)' 'SoundPlugin 27 February 2009 (e)' 'BitBltPlugin 8 April 2009 (e)' 'LargeIntegers v1.5 27 February 2009 (e)' 'MiscPrimitivePlugin 27 February 2009 (e)' 'SecurityPlugin 27 February 2009 (e)' 'FilePlugin 27 February 2009 (e)')
>> So it looks as if the necessary plugin is there (Smalltalk vmVersion
>> 'Pharo0.1 of 16 May 2008 [latest update: #10074]')
>>
>> I think there's a small bug in OSProcessAccessor
>> class>>forThisOSProcess. I changed the last 2 lines to be
>> oldAccessor ifNotNil:
>> [oldAccessor release; finalize.].
>> ^ ThisOSProcessAccessor := self concreteClass basicNew initialize]
>> I added the ifNotNil: test; without it release fails because it is sent
>> to an undefined object. The ifNotNil: test probably belongs earlier in
>> the code, but this was enough to get it to run.
>>
>> However, the final initialize fails. It calls
>> UnixOSProcessAccessor>>grimReaperProcess, which fails because grimReaper
>> is nil. I notice the very last OSProcess changeset touched this method.
>>
> I think there are 2 separate problems. First, the parentheses are off.
> I think they should be
> grimReaperProcess
> "This is a process which waits for the death of a child OSProcess, and
> informs any dependents of the change. Use SIGCHLD events if possible,
> otherwise a Delay to poll for exiting child processes."
>
> | event processSynchronizationDelay |
> ^ self canAccessSystem
> ifTrue:
> [event := (self canAccessSystem and: [self canForwardExternalSignals])
> ifTrue: [self sigChldSemaphore]
> ifFalse: [Delay forMilliseconds: 200].
> processSynchronizationDelay := Delay forMilliseconds: 20.
> grimReaper ifNil:
> [grimReaper :=
> [[event wait.
> processSynchronizationDelay wait. "Avoids lost signals in heavy process switching"
> self changed: #childProcessStatus] repeat] fork.].
> "name selected to look reasonable in the process browser"
> grimReaper name: ((ReadStream on: grimReaper hash asString) next: 5)
> , ': the child OSProcess watcher']
> ifFalse:
> [nil]
> I moved a parentheses from after 'OSProcess watcher' on the 3rd to last
> line to after the fork. I also added "." after the ].
>
> The second problem is that fork in Cuis does not return an object. This
> is perhaps related to the bug that inspired the latest OSProcess
> release. There's a very informative comment on the Cuis fork method:
> fork
> "Create and schedule a Process running the code in the receiver."
>
> "jmv - Do NOT answer the new process.
>
> See http://lists.squeakfoundation.org/pipermail/squeak-dev/2008-February/124960.html
>
> Most times, this methods returns before resuming the new process (if priority of new process is less
> or equal than current). But it might return afterwards.
>
> This means it is very dangerous to use the returned process in code that stores it in some variable
> and checks for nil to start a new one. If this methods happens to return after the new process is forked,
> chances are the code that starts all this runs again, that variable is nil, and a second process is forked,
> perhaps breaking some shared state. This kind of bug is hard to spot and debug.
>
> Callers wanting the new process object, should call #newProcess, store the answer, and then #resume.
>
> A way to ensure this bug will not ever happen again is just to answer nil"
>
> self newProcess resume.
> ^nil
>
> I think the fix is to do that (newProcess and resume), but perhaps this
> means some of the syncronization code in the current grimReaperProcess
> can go.
>
> Ross
>
> P.S. The original error arose when grimReaper name: failed.
I believe it would be better to have #fork and friends return nil also
in Squeak. It is much easier to fix senders...
Another alternative, even more radical is to have #fork and friends do
self error: 'Never call this method. Use #newProcess and #resume instead'
to make senders easier to spot. You needed to figure yourself that the
answer of #fork was nil. The argument against this is that there are
"legitimate" senders of #fork, i.e. code that does not use the returned
value...
Cheers,
Juan Vuletich
More information about the Squeak-dev
mailing list
|