guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Core dump when throwing an exception from a resumed partial continua


From: Andrew Gaylard
Subject: Re: Core dump when throwing an exception from a resumed partial continuation
Date: Thu, 21 Mar 2013 15:53:08 +0200
User-agent: Mozilla/5.0 (X11; SunOS sun4u; rv:17.0) Gecko/20130108 Thunderbird/17.0.2

On 03/21/13 11:43, Andy Wingo wrote:
On Fri 15 Mar 2013 22:01, Brent Pinkney <address@hidden> writes:

When I resume the continuation in another thread, all works perfectly
UNLESS the continued execution throws and exception.
Then guile exits with a core dump.

By contrast if I resume the continuation in the same thread and then
throw and exception all works as expected.
I think I know what this is.

So, a delimited continuation should capture that part of the dynamic
environment made in its extent.  (See Oleg Kiselyov and Chung-Chieh
Shan's "Delimited Dynamic Binding" paper.)  That is what Guile does, for
fluids, prompts, and dynamic-wind blocks.

Our implementation of exception handling uses a fluid,
%exception-handler (boot-9.scm:86).  However that fluid references a
stack of exception handlers on the heap.  There is the problem: an
exception in a reinstated delimited continuation continuation will walk
the captured exception handler stack from the heap, not from its own
dynamic environment.  Therefore it could abort to a continuation that is
not present on the new thread.

The solution is to have the exception handler find the next handler from
the dynamic environment.  This will need a new primitive to walk the
dynamic stack, I think.

I can't look at this atm as I broke my arm (!) and so typing is tough.
For now as a workaround I suggest you put a catch #t in each of your
delimited continuations.  This way all throws will be handled by catches
established by the continuation.

Regards,

Andy
Andy,

Thanks for giving this some thought -- sorry to hear about your arm!

This does shed some light on things. If I change this:

(throw 'oops) ; should not crash the vm

to this:

(catch #t
(λ ()
(throw 'oops)) ; should not crash the vm
(λ ()
(display "Success!")(newline))) ; never reached

the VM still cores; "Success" is never shown. However, you've probably
spotted my mistake: the handler should be (λ (key . args) ... ).

But this core shows up differently in the stack-trace in gdb:

#0 scm_error (key=0x1001854c0, subr=0x0, message=0xffffffff7e7ef518 "Wrong number of arguments to ~A", args=0x100db95b0, rest=0x4) at error.c:62

... which is exactly the exception one would expect. Fixing the handler thus:

(catch #t
(λ ()
(throw 'oops)) ; should not crash the vm
(λ (key . args)
(display "Success!")(newline))) ; works!

...solves the problem, and the VM doesn't core any more.

So it seems that although we *did* have a catch around our resumption,
there must have been some (different) error in its handler, which caused a
second exception, which caused the VM to crash.

Unfortunately, the test-case we made handles this second exception fine.
It'd be great to be able to distill this problem down to a pithy test-case.
(Our app is 4500 lines and still growing, so it's not really a candidate to
send to the list.)

The same problem happens (VM cores) if I do this:

(catch 'not-oops
(λ ()
(throw 'oops)) ; should not crash the vm
(λ (key . args)
(display "Success!")(newline))); never reached

So your answer to surround the resumption with a (catch #t ...) is a
good workaround. For our code, anyway.

(I'm now off to go read http://www.cs.indiana.edu/~sabry/papers/delim-dyn-bind.pdf :)
--
Andrew




reply via email to

[Prev in Thread] Current Thread [Next in Thread]