Replacing a StandardToolSet

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

Replacing a StandardToolSet

Igor Stasenko
Hello again,

i'm stuck with a code to handle errors in squeak image.
I want to replace the default behavior, when unhandled error occurs is
to same as user pressing 'Abort' button.

This is a code snippet, how i doing this:

----
HydraDebugToolSet>>debugError: anError
        recursed == true ifTrue: [ ^ Processor terminateActive ].
        recursed := true.

        Transcript show: 'Error in interpreter (', HydraVM
myInterpreterInstance asString , ')',
                String cr,
                anError description,
                String cr,
                anError signalerContext shortStack.

        Smalltalk
                logError: anError description
                inContext: anError signalerContext
                to: 'HydraDebug.log'.

        recursed := false.
        Processor terminateActive.
        ^ nil

----------

The problem in doing Processor terminateActive - i'm not sure if this
works exactly as abandoning process.
And i'm stuck, because if i don't put Processor terminateActive, then
it starts an infinite loop barfing on sending unknown message to nil
(i suspect that it's because i returning nil at exit).
But if i leave process termination , then interpreter exits very early
blaming me, that there is no scheduled processes left.
Does it means, that all processes in image stepped on error and i
killed them, or it just means, that there is no processes which can be
scheduled at current point of time (some can wait on semaphore for
external event occur).

Can anyone, please, advice, how to make this stinky code to work
without causing troubles?

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Replacing a StandardToolSet

Tom Phoenix
On Feb 6, 2008 12:21 AM, Igor Stasenko <[hidden email]> wrote:

> i'm stuck with a code to handle errors in squeak image.
> I want to replace the default behavior, when unhandled error occurs is
> to same as user pressing 'Abort' button.
>
> This is a code snippet, how i doing this:
>
> ----
> HydraDebugToolSet>>debugError: anError
>         recursed == true ifTrue: [ ^ Processor terminateActive ].
>         recursed := true.
>
>         Transcript show: 'Error in interpreter (', HydraVM
> myInterpreterInstance asString , ')',
>                 String cr,
>                 anError description,
>                 String cr,
>                 anError signalerContext shortStack.
>
>         Smalltalk
>                 logError: anError description
>                 inContext: anError signalerContext
>                 to: 'HydraDebug.log'.
>
>         recursed := false.
>         Processor terminateActive.
>         ^ nil

There's something about that variable 'recursed' that smells wrong. I
think it's that you're trying to make your code reentrant, but you're
not testing and setting that flag atomically. Maybe you need to use a
Semaphore?

> The problem in doing Processor terminateActive - i'm not sure if this
> works exactly as abandoning process.
> And i'm stuck, because if i don't put Processor terminateActive, then
> it starts an infinite loop barfing on sending unknown message to nil
> (i suspect that it's because i returning nil at exit).

Exactly; you need to make a method that, unlike any normal method,
never returns. Part of the trouble is that sometimes the current
process is the UI process, which needs to be replaced before it's
terminated. I think you need to end your method with something like
this:

    Project spawnNewProcessIfThisIsUI: Processor activeProcess.
    Processor terminateActive.  "stop here"
    ^self error: 'This line should never be reached.'.

I'm not completely sure whether that is the Right Thing to Do in all
circumstances, especially under the Hydra VM. Does that work for you?
Good luck with it!

--Tom Phoenix

Reply | Threaded
Open this post in threaded view
|

Re: Replacing a StandardToolSet

Igor Stasenko
Thanks for answer :)

On 06/02/2008, Tom Phoenix <[hidden email]> wrote:

> On Feb 6, 2008 12:21 AM, Igor Stasenko <[hidden email]> wrote:
>
> > i'm stuck with a code to handle errors in squeak image.
> > I want to replace the default behavior, when unhandled error occurs is
> > to same as user pressing 'Abort' button.
> >
> > This is a code snippet, how i doing this:
> >
> > ----
> > HydraDebugToolSet>>debugError: anError
> >         recursed == true ifTrue: [ ^ Processor terminateActive ].
> >         recursed := true.
> >
> >         Transcript show: 'Error in interpreter (', HydraVM
> > myInterpreterInstance asString , ')',
> >                 String cr,
> >                 anError description,
> >                 String cr,
> >                 anError signalerContext shortStack.
> >
> >         Smalltalk
> >                 logError: anError description
> >                 inContext: anError signalerContext
> >                 to: 'HydraDebug.log'.
> >
> >         recursed := false.
> >         Processor terminateActive.
> >         ^ nil
>
> There's something about that variable 'recursed' that smells wrong. I
> think it's that you're trying to make your code reentrant, but you're
> not testing and setting that flag atomically. Maybe you need to use a
> Semaphore?
>

Well, it's a dead-simple inst var. I do a little care if it's set
non-atomically.
Event if error will recurse for a couple of times, not a big deal.
The main reason of having it,  is to prevent infinite recursion in a long term.
But you highlighted another problem: given code is not thread-safe.
If scheduler will decide to stop in the middle of error handling and
switch to another process, where error will occur too, this could lead
to problems.
So, in perfect, error handling code should be guarded by semaphore.
Also, i would recommend doing same for main squeak image.

> > The problem in doing Processor terminateActive - i'm not sure if this
> > works exactly as abandoning process.
> > And i'm stuck, because if i don't put Processor terminateActive, then
> > it starts an infinite loop barfing on sending unknown message to nil
> > (i suspect that it's because i returning nil at exit).
>
> Exactly; you need to make a method that, unlike any normal method,
> never returns. Part of the trouble is that sometimes the current
> process is the UI process, which needs to be replaced before it's
> terminated. I think you need to end your method with something like
> this:
>
>     Project spawnNewProcessIfThisIsUI: Processor activeProcess.
>     Processor terminateActive.  "stop here"
>     ^self error: 'This line should never be reached.'.
>
> I'm not completely sure whether that is the Right Thing to Do in all
> circumstances, especially under the Hydra VM. Does that work for you?
> Good luck with it!
>

You're right, except that, i don't have UI process in non-interactive
image, because it pointless to have it. :)
I stubbed out the code by replacing UIManager to simply produce error
at any attempt when something tries to use UI.
And HydraDebugToolSet class, which handles errors should simply put
message to transcript, again, without involving any UI (popping up
debugger e.t.c).

Any attempt to use UI in non-interactive image, currently leads to
error (due to primitives failure).
So, mainly, i was in need of this class to see, if background image
starts cleanly , by checking what errors it produces during startup.

--
Best regards,
Igor Stasenko AKA sig.