[POLL] Process>>terminate
Gary Chambers
gazzaguru2 at btinternet.com
Mon Oct 15 19:05:22 UTC 2007
That seems like the correct solution to me.
> -----Original Message-----
> From: squeak-dev-bounces at lists.squeakfoundation.org
> [mailto:squeak-dev-bounces at lists.squeakfoundation.org]On Behalf Of Igor
> Stasenko
> Sent: 15 October 2007 7:55 PM
> To: The general-purpose Squeak developers list
> Subject: Re: [POLL] Process>>terminate
>
>
> Lukas Renggli:
>
> - #terminate can badly harm system if two processes concurrently try
> to terminate a third process.
>
> Yes, and that means that #terminate must be enclosed by semaphore to
> ensure that termination code evaluated only once.
> And moreover, things must be harvested to see, what is happening when
> process which causes other process to terminate terminating too ..
> like:
>
> proc := [ ... ] fork.
> [ proc terminate ] fork terminate.
>
>
> On 15/10/2007, Paolo Bonzini <bonzini at gnu.org> wrote:
> > > Well, I must *personally* say that I always associated #ensure: and
> > > friends with the exception framework - thus, yes, I also want
> my ensure:
> > > blocks to run - when there are *exceptions* thrown - but also when the
> > > Process is *terminated*?
> >
> > That's the source of the misunderstanding. #ensure: is completely
> > detached from the exception framework. In fact, you can implement
> > exceptions only with thisContext, but it's really hard to implement
> > #ensure: correctly without support in the virtual machine. #ensure: and
> > #ifCurtailed: blocks, for example, are run also when a block performs a
> > non-local return, as in
> >
> > ^[ ^#outer ] ensure: [ Transcript show: 'executed' ]
> > ^[ ^#outer ] ifCurtailed: [ Transcript show: 'executed' ]
> >
> > Note that #ifCurtailed: and #ensure: are equally powerful. Here is
> > #ifCurtailed: implemented with #ensure: and vice versa:
> >
> > BlockClosure>>ifCurtailed: curtailedBlock
> > | result |
> > curtailed := true.
> > ^[ result := aBlock value. curtailed := false. result ]
> > ensure: [ curtailed ifTrue: [ curtailedBlock value ] ]
> >
> > BlockClosure>>ensure: ensureBlock
> > | result |
> > [ result := aBlock value ] ifCurtailed: [
> > ensureBlock value.
> > ^result ].
> > "Don't reenter the ensureBlock if it is curtailed!"
> > ensureBlock value.
> > ^result
> >
> > > - #ensure: blocks are evaluated in the wrong process, that is the
> > > process that calls #terminate not the one that runs the process. This
> > > can have very strange effects, if your code depends on the current
> > > process.
> >
> > This can be solved easily. You define a ProcessBeingTerminated
> > exception and wrap the process block aBlock into something like this:
> >
> > BlockClosure>>newProcess
> > ^Process
> > forContext: self processBlock
> > priority: Processor userSchedulingPriority
> >
> > BlockClosure>>processBlock
> > ^[[aBlock
> > on: ProcessBeingTerminated
> > do: [:sig |
> > "If we terminate in the handler, the 'ensure' blocks
> > are not evaluated. Instead, if the handler returns, the
> > unwinding is done properly."
> > sig return]]
> > ensure: [self primTerminate]]
> >
> >
> > where #primTerminate is the "hard terminate" that Igor was mentioning.
> >
> > Process>>primTerminate
> > self isActiveProcess ifFalse: [ self error: 'booh' ].
> > thisContext terminateTo: nil.
> > self suspend
> >
> >
> > and termination becomes a matter of signaling the exception:
> >
> > ProcessorScheduler>>isProcessReady: aProcess
> > ^aProcess suspendingList ==
> > (quiescentProcessLists at: aProcess priority)
> >
> > Process>>isReady
> > ^Processor isProcessReady: self
> >
> > Process>>terminate
> > | pbt |
> > "A while ago I explained how to use this to properly implement
> > Semaphore>>#critical:."
> > pbt := ProcessBeingTerminated new.
> > self isReady ifFalse: [ pbt semaphore: myList ].
> > self signalException: pbt.
> >
> >
> > You can do whatever you want with this code, it is not taken from GNU
> > Smalltalk.
> >
> > Paolo
> >
>
> For cases, when my process is terminated and i need to execute some
> code before(or at the moment) when this happens, better, i think is to
> provide a #onTerminated: method for Process, where you can put a
> hadler which will be executed whenever process is going to be
> terminated. In normal conditions, if process finished w/o explicit
> call to #terminate, this code should not be invoked.
>
> So, you can just write something like that:
>
> [ ... ] fork onTerminate: [ :p | Transcript show: 'Ouch, i terminated
> by..' , p name ]
>
> or even #addOnTerminate: block , which will add a block to a list of
> blocks which will be evaluated when process is terminating.
>
> Also, i not agree that terminate must be connected with exceptions.
> Process provides a ways how to control its execution flow, and its not
> an exceptional behavior, its a part of its interface. And i think that
> exceptions framework must not be involved here.
> Of course, its just my humble opinion :)
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
More information about the Squeak-dev
mailing list
|