<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
</style>
</head>
<body class='hmmessage'>
1) Should we just always use sigsetjmp/siglongjmp?<BR>
Or, getting the signal mask is much extra expense usually unnecesary?<BR>
(imagine the case of there being a stack walker, where not even setjmp is paid for)<BR>
Folks aren't supposed to muck with it willy nilly and should expect raising/catching an exception to restore to that which it was at the point of the try?<BR>
<BR>
<BR>
2) The inlined NULL checks arounds the "barrier" calls: <BR>
- Aren't they just bloating the code for the unusual case? <BR>
- Aren't they better left in the barrier functions themselves? <BR>
- Besides leading to smaller and therefore faster code (except in the usual<BR>
case of there being a NULL pointer deref, which is always going to be slow anyway),<BR>
can't this then double or mostly double for a place to fix this?<BR>
That is, IF, but I doubt this is true, IF every pointer deref goes through a "barrier"<BR>
function, the exceptions could be raised from them, right?<BR>
<BR>
<BR>
Are the barrier calls placed adequately maybe?????<BR>
I don't think they are placed for untraced derefs (a fix Tony recently put in)<BR>
and I imagine you might want those to act the same as traced null derefs.<BR>
Maybe a pragma???<BR>
<BR>
<BR> - Jay<BR><BR> <BR>> To: hosking@cs.purdue.edu<BR>> Date: Mon, 27 Apr 2009 18:18:10 -0700<BR>> From: mika@async.caltech.edu<BR>> CC: m3devel@elegosoft.com<BR>> Subject: Re: [M3devel] RuntimeError doesn't work quite as advertised<BR>> <BR>> I think it ought to be safe to use siglongjmp.<BR>> <BR>> So we could attach a sigjmpbuf to whatever structure PushEFrame<BR>> builds only when it's doing it for a "RuntimeError", and on a runtime<BR>> error that's not handled otherwise, we catch the unix signal and<BR>> call siglongjmp to get back to the exception handler...<BR>> <BR>> Here's an example in C:<BR>> <BR>> #include <setjmp.h><BR>> #include <signal.h><BR>> <BR>> sigjmp_buf env;<BR>> <BR>> void handler(int x) { siglongjmp(env,1); }<BR>> <BR>> main()<BR>> {<BR>> signal(SIGSEGV, handler);<BR>> <BR>> if(sigsetjmp(env,1)) {<BR>> printf("caught signal\n");<BR>> exit(0);<BR>> } else {<BR>> printf("initialized env\n");<BR>> }<BR>> <BR>> {<BR>> int *a=(void *)0;<BR>> printf("a is %d\n", *a /* SEGV */); <BR>> /* not reached */<BR>> }<BR>> }<BR>> <BR>> Mika<BR>> <BR>> <BR>> Tony Hosking writes:<BR>> >It's probably not generally safe to use RAISE inside a signal <BR>> >handler. There are esoteric rules as to what signal handlers can <BR>> >handle...<BR>> ><BR>> >I think we need to think harder on how best to reflect NIL dereference <BR>> >as a signal. Perhaps we need explicit NIL checks after all...<BR>> ><BR>> >On 27 Apr 2009, at 18:31, Mika Nystrom wrote:<BR>> ><BR>> >> Ok so I tried the "obvious thing", namely, I changed RTSignal.SegV to<BR>> >> do<BR>> >><BR>> >> RAISE RuntimeError.E(RuntimeError.T.BadMemoryReference);<BR>> >><BR>> >> Somewhat to my surprise, this does the right thing for a null method.<BR>> >> But somewhat less surprisingly, it loops for NilJump and NilDeref.<BR>> >> Is the machine jumping back and re-executing the same instructions<BR>> >> after the signal handler returns?<BR>> >><BR>> >> Would all hell break loose if one were to special-case EXCEPT<BR>> >> RuntimeError.E to store a thread-local jmp_buf that one does a<BR>> >> C-style longjmp to? (With a chain back to any higher RuntimeError.E<BR>> >> handlers, I suppose...) Or is there a way to get the exception to<BR>> >> work out of the signal handler with the normal exception mechanism?<BR>> >><BR>> >> Mika<BR>> ><BR>> >> Mika Nystrom writes:<BR>> >>><BR>> >>> Maybe someone else knows more about this than me...<BR>> >>><BR>> >>> The following program:<BR>> >>><BR>> >>> MODULE Main;<BR>> >>> IMPORT RuntimeError, IO;<BR>> >>><BR>> >>> PROCEDURE Range() = BEGIN EVAL VAL(-1,CARDINAL) END Range;<BR>> >>><BR>> >>> PROCEDURE Assert() = BEGIN <*ASSERT FALSE*> END Assert;<BR>> >>><BR>> >>> PROCEDURE NilJump() = VAR x : PROCEDURE() := NIL; BEGIN x() END <BR>> >>> NilJump;<BR>> >>><BR>> >>> PROCEDURE NilDeref() =<BR>> >>> VAR x : REF INTEGER := NIL; b : INTEGER;<BR>> >>> BEGIN b := x^ END NilDeref;<BR>> >>><BR>> >>> PROCEDURE NilMethod() =<BR>> >>> TYPE T = OBJECT METHODS m() END;<BR>> >>> VAR t : T; BEGIN t.m() END NilMethod;<BR>> >>><BR>> >>> BEGIN<BR>> >>> WITH ps = ARRAY OF PROCEDURE() { Range, Assert, NilMethod, NilJump, <BR>> >>> NilDeref } DO<BR>> >>> FOR i := FIRST(ps) TO LAST(ps) DO<BR>> >>> TRY<BR>> >>> ps[i]()<BR>> >>> EXCEPT<BR>> >>> RuntimeError.E(e) => IO.Put("RuntimeError: " & <BR>> >>> RuntimeError.Tag(e) & " \n")<BR>> >>> END<BR>> >>> END<BR>> >>> END<BR>> >>> END Main.<BR>> >>><BR>> >>> yields the following result:<BR>> >>><BR>> >>> (1053)trs80:~/test/src>../FreeBSD4/prog<BR>> >>> RuntimeError: An enumeration or subrange value was out of range.<BR>> >>> RuntimeError: <*ASSERT*> failed.<BR>> >>><BR>> >>><BR>> >>> ***<BR>> >>> *** runtime error:<BR>> >>> *** Segmentation violation - possible attempt to dereference NIL<BR>> >>> *** pc = 0x8048a71 = NilMethod + 0x10 in ../src/Main.m3<BR>> >>> ***<BR>> >>><BR>> >>> Abort<BR>> >>><BR>> >>> Seems to me I ought to see a few more exceptions and not a crash.<BR>> >>><BR>> >>> I'm happy to investigate a bit more, but does anyone have a clue <BR>> >>> where<BR>> >>> to begin?<BR>> >>><BR>> >>> Mika<BR></body>
</html>