[Annoying] Single-process deadlock in VW7.4 -- hole in #ensure: w.r.t. #terminate

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[Annoying] Single-process deadlock in VW7.4 -- hole in #ensure: w.r.t. #terminate

Martin McClure
I've managed (accidentally) to get a 7.4 Process to be deadlocked with
itself. The key is to send #terminate to the Process when it's at just
the wrong point.

This is clearly not desirable behavior. However, I'm not sure what the
desirable behavior is. I'm interested in hearing your opinions on the
subject.


Here's the sequence the Process follows:

*  Sends #critical: aBlock to a Semaphore.
*  The Semaphore does a #wait.
*  aBlock is evaluated, and completes.
*  The Semaphore should now signal itself. This signal is in an
    #ensure: block.
*  Just before the #ensure: block is entered, the Process is
    sent #terminate.
*  The #terminate causes the stack to unwind and all unwind blocks
    to run. HOWEVER, because we've already entered
    #valueAsUnwindBlockFrom: for the #ensure: block, it is *not*
    evaluated. The Semaphore is not signaled.
*  All unwind blocks deeper on the stack are evaluated.
*  One of these unwind blocks sends #critical: to our Semaphore.
*  Since the Semaphore has not been signaled, the Process hangs
    at this point.


The core of this problem seems to be that unwind blocks should not be
executed in response to an error inside the unwind block, but that
creates a hole in unwind block behavior when #terminate (and possibly
#interruptWith:) are sent.

So my question right now is whether there's a way to improve this.
Putting a marker on the stack when interrupting a Process could be used
to complete an interrupted unwind block on unwind, while unwind blocks
that raise an exception during their own execution would not be
completed. However, this could make it difficult to terminate processes
that had misbehaving and long-running unwind blocks.

What do you think?

Thanks,

-Martin


For the curious, here's a stack excerpt. Full stack available on request.

Debug process
GbxRecursionLock(Semaphore)>>waitIfCurtailedSignal
GbxRecursionLock(Semaphore)>>critical:

...

GbsSession>>logout
optimized [] in GbsSession>>loginLinked:
BlockClosure>>valueAsUnwindBlockFrom:
BlockClosure>>evaluateUnwindBlockFor:
MethodContext>>evaluateUnwind
TerminateException(GenericException)>>unwind
TerminateException(GenericException)>>return:
TerminateException(GenericException)>>return
optimized [] in [] in Process class>>forBlock:priority:
TerminateException(GenericException)>>performHandler:
TerminateException(GenericException)>>propagatePrivateFrom:
TerminateException(GenericException)>>propagateFrom:
TerminateException(GenericException)>>propagate
TerminateException(GenericException)>>raiseSignal
TerminateException class(GenericException class)>>raise
optimized [] in Process>>terminate
BlockClosure>>on:do:
Process>>terminate
optimized [] in [] in Process>>terminate
BlockClosure>>valueAsUnwindBlockFrom:
BlockClosure>>ensure:
GbxRecursionLock(Semaphore)>>critical:

...




Reply | Threaded
Open this post in threaded view
|

Re: [Annoying] Single-process deadlock in VW7.4 -- hole in #ensure: w.r.t. #terminate

Reinout Heeck-2
Martin McClure wrote:
> The core of this problem seems to be that unwind blocks should not be
> executed in response to an error inside the unwind block, but that
> creates a hole in unwind block behavior when #terminate (and possibly
> #interruptWith:) are sent.

I guess we need to differentiate between exceptions risen in-process
(possibly in a broken unwind block) and those risen by an other process.
IOW it seems only #interruptWith: needs special treatment.


R
-