[M3devel] RuntimeError doesn't work quite as advertised
Tony Hosking
hosking at cs.purdue.edu
Tue Apr 28 03:48:34 CEST 2009
On 28 Apr 2009, at 11:18, Mika Nystrom wrote:
> I think it ought to be safe to use siglongjmp.
>
> So we could attach a sigjmpbuf to whatever structure PushEFrame
> builds only when it's doing it for a "RuntimeError", and on a runtime
> error that's not handled otherwise, we catch the unix signal and
> call siglongjmp to get back to the exception handler...
I'm not sure we can statically determine how a frame will be used.
Can someone (Jay?) confirm whether signal handling on platforms
without a stack walker are actually already using siglongjmp? I have
a feeling this may already be the case.
> Here's an example in C:
>
> #include <setjmp.h>
> #include <signal.h>
>
> sigjmp_buf env;
>
> void handler(int x) { siglongjmp(env,1); }
>
> main()
> {
> signal(SIGSEGV, handler);
>
> if(sigsetjmp(env,1)) {
> printf("caught signal\n");
> exit(0);
> } else {
> printf("initialized env\n");
> }
>
> {
> int *a=(void *)0;
> printf("a is %d\n", *a /* SEGV */);
> /* not reached */
> }
> }
>
> Mika
>
>
> Tony Hosking writes:
>> It's probably not generally safe to use RAISE inside a signal
>> handler. There are esoteric rules as to what signal handlers can
>> handle...
>>
>> I think we need to think harder on how best to reflect NIL
>> dereference
>> as a signal. Perhaps we need explicit NIL checks after all...
>>
>> On 27 Apr 2009, at 18:31, Mika Nystrom wrote:
>>
>>> Ok so I tried the "obvious thing", namely, I changed RTSignal.SegV
>>> to
>>> do
>>>
>>> RAISE RuntimeError.E(RuntimeError.T.BadMemoryReference);
>>>
>>> Somewhat to my surprise, this does the right thing for a null
>>> method.
>>> But somewhat less surprisingly, it loops for NilJump and NilDeref.
>>> Is the machine jumping back and re-executing the same instructions
>>> after the signal handler returns?
>>>
>>> Would all hell break loose if one were to special-case EXCEPT
>>> RuntimeError.E to store a thread-local jmp_buf that one does a
>>> C-style longjmp to? (With a chain back to any higher RuntimeError.E
>>> handlers, I suppose...) Or is there a way to get the exception to
>>> work out of the signal handler with the normal exception mechanism?
>>>
>>> Mika
>>
>>> Mika Nystrom writes:
>>>>
>>>> Maybe someone else knows more about this than me...
>>>>
>>>> The following program:
>>>>
>>>> MODULE Main;
>>>> IMPORT RuntimeError, IO;
>>>>
>>>> PROCEDURE Range() = BEGIN EVAL VAL(-1,CARDINAL) END Range;
>>>>
>>>> PROCEDURE Assert() = BEGIN <*ASSERT FALSE*> END Assert;
>>>>
>>>> PROCEDURE NilJump() = VAR x : PROCEDURE() := NIL; BEGIN x() END
>>>> NilJump;
>>>>
>>>> PROCEDURE NilDeref() =
>>>> VAR x : REF INTEGER := NIL; b : INTEGER;
>>>> BEGIN b := x^ END NilDeref;
>>>>
>>>> PROCEDURE NilMethod() =
>>>> TYPE T = OBJECT METHODS m() END;
>>>> VAR t : T; BEGIN t.m() END NilMethod;
>>>>
>>>> BEGIN
>>>> WITH ps = ARRAY OF PROCEDURE() { Range, Assert, NilMethod, NilJump,
>>>> NilDeref } DO
>>>> FOR i := FIRST(ps) TO LAST(ps) DO
>>>> TRY
>>>> ps[i]()
>>>> EXCEPT
>>>> RuntimeError.E(e) => IO.Put("RuntimeError: " &
>>>> RuntimeError.Tag(e) & " \n")
>>>> END
>>>> END
>>>> END
>>>> END Main.
>>>>
>>>> yields the following result:
>>>>
>>>> (1053)trs80:~/test/src>../FreeBSD4/prog
>>>> RuntimeError: An enumeration or subrange value was out of range.
>>>> RuntimeError: <*ASSERT*> failed.
>>>>
>>>>
>>>> ***
>>>> *** runtime error:
>>>> *** Segmentation violation - possible attempt to dereference NIL
>>>> *** pc = 0x8048a71 = NilMethod + 0x10 in ../src/Main.m3
>>>> ***
>>>>
>>>> Abort
>>>>
>>>> Seems to me I ought to see a few more exceptions and not a crash.
>>>>
>>>> I'm happy to investigate a bit more, but does anyone have a clue
>>>> where
>>>> to begin?
>>>>
>>>> Mika
More information about the M3devel
mailing list