digitalmars.D - un-catched segfault exception
- philippe quesnel (16/16) Jan 09 2008 I have a bug that causes a segmentation fault (null object)...
- Christopher Wright (66/87) Jan 09 2008 This certainly can be normal behavior -- C++ does it this way, after
- Hxal (17/25) Jan 09 2008 I have played with throwing exceptions out of signal handlers and
- Christopher Wright (4/33) Jan 09 2008 I haven't had much need for this stuff yet -- I do mostly
- BCS (7/18) Jan 10 2008 I've never seen this.
- Hxal (5/6) Jan 10 2008 My bad, I must have remembered wrong, it does indeed work fine
- Hxal (27/33) Jan 11 2008 Actually, I remembered what is the problem with throwing exceptions
- Hxal (4/6) Jan 10 2008 Just a small correction: you need -fexceptions or -funwind-tables,
- Jason House (3/6) Jan 10 2008 Your project looks interesting. I'd be especially interested in seeing ...
- Jarrett Billingsley (4/13) Jan 10 2008 Well you're obviously using Tango; Tango's had traced exceptions for a
- Jason House (5/22) Jan 10 2008 Stupid question - what functionality will that get me? A full backtrace...
- Robert Fraser (3/25) Jan 11 2008 Flectioned gives segfault tracing on Linux. If a Windows-compatible way
- BCS (5/8) Jan 10 2008 Why would this be slow? seg-v are caused by hardware. When a seg-v is
- Christopher Wright (3/14) Jan 10 2008 Handling an error will be slower. Handling a lack of an error will be
- BCS (8/27) Jan 11 2008 "Exceptions are a slow way to handle a seg-v's after it happens"
- Christopher Wright (7/37) Jan 12 2008 I was speaking about the case where you're using exceptions as flow
- Michiel Helvensteijn (5/8) Jan 14 2008 Hehe. :-)
- Jarrett Billingsley (3/20) Jan 09 2008 That's funny, cause on DMDWin you _can_ catch them.
- philippe.quesnel (12/16) Jan 10 2008 I just did a test C++ app in Windows (MsDev) ..
- Sean Kelly (7/16) Jan 10 2008 Segfaults in Windows pass through the Structured Exception Handling
- Robert Fraser (2/20) Jan 11 2008 Any way to get Flectioned tracing them?
- Sean Kelly (6/24) Jan 11 2008 Generating a stack trace within a signal handler would probably work,
- philippe.quesnel (17/17) Jan 10 2008 ok, it seems this is a Windows vs 'Unix' difference...
I have a bug that causes a segmentation fault (null object)... but try/catch fails to catch it !! ?? even with catch (Exception e) ... catch (Error e) ... catch // "last catch" ... I still cant catch the exception & the app crashes. I'm on Windows (XP), with gdc.exe (GCC) 3.4.5 (mingw special) (gdc 0.24, using dmd 1.020). I must be missing some important point here .. this cant be the normal behaviour !!?? any help / suggestions would be appreciated. thank you Philippe
Jan 09 2008
philippe quesnel wrote:I have a bug that causes a segmentation fault (null object)... but try/catch fails to catch it !! ?? even with catch (Exception e) ... catch (Error e) ... catch // "last catch" ... I still cant catch the exception & the app crashes. I'm on Windows (XP), with gdc.exe (GCC) 3.4.5 (mingw special) (gdc 0.24, using dmd 1.020). I must be missing some important point here .. this cant be the normal behaviour !!?? any help / suggestions would be appreciated. thank you PhilippeThis certainly can be normal behavior -- C++ does it this way, after all. A segfault is not an exception or an error; it's a signal. You can trap the segfault with a signal handler but you can't catch it in a try/catch block. With exceptions, your program essentially contains a try/catch block around all your code that terminates your program if you didn't handle the exception. That's probably not correct, but it's close enough for my purposes at the moment. With signals, the operating system essentially registers a signal handler; when it gets signal, it determines which application is responsible. If that application has a signal handler, that handler is called; otherwise, your program is toast. What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous. Someone else probably has a cleaner version, but here's something that I cooked up a couple weeks back. Tested on Linux, dmd1.023-ish; not guaranteed to work for you. It might destroy your computer, kill your firstborn, raise Cthulhu from the depths, overwrite your doctoral thesis with dancing hamsters, et cetera. The whole point of this code is getting a stack trace rather than an opaque segfault message (if you're using Tango, just inherit from TracedException rather than Exception and reference Flectioned by Thomas Kuehne). It is unreasonable to use anything like this as a regular means of flow control, due to performance reasons and the hideousness of using exceptions for flow control aside from error handling. /** Public domain. Traps SIGSEGV and throws an exception, so you should get a stack trace when you segfault. */ class NullReferenceException : Exception { this (char[] msg) { super(msg); } this () { super ("tried to dereference a pointer to a nonexistent memory region"); } } const int SA_SIGINFO = 4; const int SIGSEGV = 11; extern(C) { struct sig_action { // Dunno if a function* would work here... void* action; int flags; void* restorer; } int sigaction (int signal, sig_action* action, sig_action* oact); } void segv_throw (int i) { throw new NullReferenceException(); } static this () { sig_action act; act.action = &segv_throw; act.flags = SA_SIGINFO; sigaction(SIGSEGV, &act, null); } debug (SegvTest) { void main () { uint* p = null; uint k = *p; } }
Jan 09 2008
Christopher Wright Wrote:What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous. Someone else probably has a cleaner version, but here's something that I cooked up a couple weeks back. Tested on Linux, dmd1.023-ish; not guaranteed to work for you. It might destroy your computer, kill your firstborn, raise Cthulhu from the depths, overwrite your doctoral thesis with dancing hamsters, et cetera.I have played with throwing exceptions out of signal handlers and it's not going to work in a reliable way at all, on Linux at least. The compiler doesn't generate exception handling frames for blocks of code it doesn't expect to throw an exception, and it doesn't expect single instructions to do so. AFAIK this is true for both dmd and gdc. When you throw an exception and the stack unwinding procedure doesn't find an EH frame, it will abort your application. gcc has two switches to remedy this: -fnon-call-exceptions that expects exceptions to be thrown from dereferences and arithmetics; and -fasynchronous-unwind-tables that generates EH frames encompassing all instructions. Alas gdc doesn't support these. I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies. PS. Throwing exceptions across C code aborts too, you can however add one of the previously mentioned flags when compiling C code.
Jan 09 2008
Hxal wrote:Christopher Wright Wrote:I haven't had much need for this stuff yet -- I do mostly metaprogramming stuff -- but thanks for the link. Whenever I do applications work, I'll use your stuff.What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous. Someone else probably has a cleaner version, but here's something that I cooked up a couple weeks back. Tested on Linux, dmd1.023-ish; not guaranteed to work for you. It might destroy your computer, kill your firstborn, raise Cthulhu from the depths, overwrite your doctoral thesis with dancing hamsters, et cetera.I have played with throwing exceptions out of signal handlers and it's not going to work in a reliable way at all, on Linux at least. The compiler doesn't generate exception handling frames for blocks of code it doesn't expect to throw an exception, and it doesn't expect single instructions to do so. AFAIK this is true for both dmd and gdc. When you throw an exception and the stack unwinding procedure doesn't find an EH frame, it will abort your application. gcc has two switches to remedy this: -fnon-call-exceptions that expects exceptions to be thrown from dereferences and arithmetics; and -fasynchronous-unwind-tables that generates EH frames encompassing all instructions. Alas gdc doesn't support these. I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies. PS. Throwing exceptions across C code aborts too, you can however add one of the previously mentioned flags when compiling C code.
Jan 09 2008
Hxal wrote:I have played with throwing exceptions out of signal handlers and it's not going to work in a reliable way at all, on Linux at least. The compiler doesn't generate exception handling frames for blocks of code it doesn't expect to throw an exception, and it doesn't expect single instructions to do so.I uses this approach and it works just fine. (DMD/Linux and IIRC DMD/Win)PS. Throwing exceptions across C code aborts too, you can however add one of the previously mentioned flags when compiling C code.I've never seen this. OTOH I don't actually catch the exception as the only thing I actually uses the exception for is a poor man's stack trace: // add this at the top of all functions. scope(failure) writef(">>"__FILE__":"~itoa!(__LINE__)~\n);
Jan 10 2008
BCS Wrote:I uses this approach and it works just fine. (DMD/Linux and IIRC DMD/Win)My bad, I must have remembered wrong, it does indeed work fine with dmd/linux; there aren't even any calls to abort in deh2.d So the problem only applies to gdc, for which the runtime uses gcc's unwind procedure from libgcc_s.
Jan 10 2008
BCS Wrote:Actually, I remembered what is the problem with throwing exceptions out of signal handlers with dmd/linux. Such exceptions leak through immediate try-catch blocks. This example would print out "caught in segfault1". void segfault1 () { try { segfault2(); } catch { writefln ("caught in sefgault1"); } } void segfault2 () { try { int* a = cast(int*) 0xdeadc0de; *a = 1; } catch { writefln ("caught in sefgault2"); } }I uses this approach and it works just fine. (DMD/Linux and IIRC DMD/Win)My bad, I must have remembered wrong, it does indeed work fine with dmd/linux; there aren't even any calls to abort in deh2.d
Jan 11 2008
PS. Throwing exceptions across C code aborts too, you can however add one of the previously mentioned flags when compiling C code.Just a small correction: you need -fexceptions or -funwind-tables, -fnon-call-exceptions and -fasynchronous-unwind-tables aren't necessary unless you're throwing out of signal handlers. (Applies to gcc)
Jan 10 2008
Hxal Wrote:I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies.Your project looks interesting. I'd be especially interested in seeing some usage examples. I'll be extremely interested when the disclaimers for stacktrace are lessened. Specifically, linux-only and "doesn't work very well for either DMD or GDC". If they were gone, I'd be using this library tonight!
Jan 10 2008
"Jason House" <jason.james.house gmail.com> wrote in message news:fm65g8$p7j$1 digitalmars.com...Hxal Wrote:Well you're obviously using Tango; Tango's had traced exceptions for a while, just get flectioned and link it in when you compile your project.I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies.Your project looks interesting. I'd be especially interested in seeing some usage examples. I'll be extremely interested when the disclaimers for stacktrace are lessened. Specifically, linux-only and "doesn't work very well for either DMD or GDC". If they were gone, I'd be using this library tonight!
Jan 10 2008
Jarrett Billingsley wrote:"Jason House" <jason.james.house gmail.com> wrote in message news:fm65g8$p7j$1 digitalmars.com...Stupid question - what functionality will that get me? A full backtrace is only part of it. The other (bigger?) part is a way to capture seg faults reliably on all platforms. My project runs on windows, linux, mac, 32-bit, and 64-bit. I have yet to find a reliable way...Hxal Wrote:Well you're obviously using Tango; Tango's had traced exceptions for a while, just get flectioned and link it in when you compile your project.I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies.Your project looks interesting. I'd be especially interested in seeing some usage examples. I'll be extremely interested when the disclaimers for stacktrace are lessened. Specifically, linux-only and "doesn't work very well for either DMD or GDC". If they were gone, I'd be using this library tonight!
Jan 10 2008
Jason House wrote:Jarrett Billingsley wrote:Flectioned gives segfault tracing on Linux. If a Windows-compatible way could be found, it might not be too hard to hack in."Jason House" <jason.james.house gmail.com> wrote in message news:fm65g8$p7j$1 digitalmars.com...Stupid question - what functionality will that get me? A full backtrace is only part of it. The other (bigger?) part is a way to capture seg faults reliably on all platforms. My project runs on windows, linux, mac, 32-bit, and 64-bit. I have yet to find a reliable way...Hxal Wrote:Well you're obviously using Tango; Tango's had traced exceptions for a while, just get flectioned and link it in when you compile your project.I've played with this a bit in my own stacktracing module (which you can find at http://zygfryd.net/jive/). The same disclaimer applies.Your project looks interesting. I'd be especially interested in seeing some usage examples. I'll be extremely interested when the disclaimers for stacktrace are lessened. Specifically, linux-only and "doesn't work very well for either DMD or GDC". If they were gone, I'd be using this library tonight!
Jan 11 2008
Christopher Wright wrote:What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous.Why would this be slow? seg-v are caused by hardware. When a seg-v is noticed it triggers an interrupt and the OS goes from there. Until you get a seg-v there should be NO cost at all. Am I missing something?
Jan 10 2008
BCS wrote:Christopher Wright wrote:Handling an error will be slower. Handling a lack of an error will be faster.What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous.Why would this be slow? seg-v are caused by hardware. When a seg-v is noticed it triggers an interrupt and the OS goes from there. Until you get a seg-v there should be NO cost at all. Am I missing something?
Jan 10 2008
Christopher Wright wrote:BCS wrote:"Exceptions are a slow way to handle a seg-v's after it happens" Ok that makes a difference. I missed that because 1) I generally assume that performance after an errors is not an issue and 2) in general my programs respond to a seg-v by quitting (with an uncaught exception) on the assumption that their is nothing else it can safely do. I'd be interested in which of theses assumptions is erroneous in your case and why.Christopher Wright wrote:Handling an error will be slower. Handling a lack of an error will be faster.What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous.Why would this be slow? seg-v are caused by hardware. When a seg-v is noticed it triggers an interrupt and the OS goes from there. Until you get a seg-v there should be NO cost at all. Am I missing something?
Jan 11 2008
BCS wrote:Christopher Wright wrote:I was speaking about the case where you're using exceptions as flow control rather than a means of error handling. So if you're just going to catch the segfault exception, log it, and quit, fine; performance doesn't matter. If you're going to do something else if you get a segfault and it isn't an error, that will be slower. Not to mention you'd get pwned in code review.BCS wrote:"Exceptions are a slow way to handle a seg-v's after it happens" Ok that makes a difference. I missed that because 1) I generally assume that performance after an errors is not an issue and 2) in general my programs respond to a seg-v by quitting (with an uncaught exception) on the assumption that their is nothing else it can safely do. I'd be interested in which of theses assumptions is erroneous in your case and why.Christopher Wright wrote:Handling an error will be slower. Handling a lack of an error will be faster.What you can do, though, is convert a signal to an exception. It's going to be a lot slower than just checking a pointer to see if it's null, but if you have traced exceptions, the debugging benefit is enormous.Why would this be slow? seg-v are caused by hardware. When a seg-v is noticed it triggers an interrupt and the OS goes from there. Until you get a seg-v there should be NO cost at all. Am I missing something?
Jan 12 2008
Christopher Wright wrote:It might destroy your computer, kill your firstborn, raise Cthulhu from the depths, overwrite your doctoral thesis with dancing hamsters, et cetera.Hehe. :-) That is all. -- Michiel
Jan 14 2008
"philippe quesnel" <philippe.quesnel gmail.com> wrote in message news:fm3q1p$su3$1 digitalmars.com...I have a bug that causes a segmentation fault (null object)... but try/catch fails to catch it !! ?? even with catch (Exception e) ... catch (Error e) ... catch // "last catch" ... I still cant catch the exception & the app crashes. I'm on Windows (XP), with gdc.exe (GCC) 3.4.5 (mingw special) (gdc 0.24, using dmd 1.020). I must be missing some important point here .. this cant be the normal behaviour !!?? any help / suggestions would be appreciated. thank you PhilippeThat's funny, cause on DMDWin you _can_ catch them.
Jan 09 2008
Jarrett Billingsley Wrote:That's funny, cause on DMDWin you _can_ catch them.I just did a test C++ app in Windows (MsDev) .. and I do catch exceptions thrown by a null ptr reference. Which is what I was expecting to happen in D. Of course I can check for a NULL ptr ... but catching exceptions is for error handling too !! bugs happen ;-) One point I forgot to mention that might be important (??) : the D code is called by C(++) code (I'm using FLTK2 gui toolkit, calling D code on events) I'll do some tests to see if I the same thing happens under 'normal' situations... thx
Jan 10 2008
philippe.quesnel wrote:Jarrett Billingsley Wrote:Segfaults in Windows pass through the Structured Exception Handling mechanism, as do many other hardware-level errors. It's the Windows response to signals in Unix. And DMD is nice enough to turn these into D exceptions for you. It sounds like GDC does its exception handling another way however, and does not. SeanThat's funny, cause on DMDWin you _can_ catch them.I just did a test C++ app in Windows (MsDev) .. and I do catch exceptions thrown by a null ptr reference. Which is what I was expecting to happen in D.
Jan 10 2008
Sean Kelly wrote:philippe.quesnel wrote:Any way to get Flectioned tracing them?Jarrett Billingsley Wrote:Segfaults in Windows pass through the Structured Exception Handling mechanism, as do many other hardware-level errors. It's the Windows response to signals in Unix. And DMD is nice enough to turn these into D exceptions for you. It sounds like GDC does its exception handling another way however, and does not. SeanThat's funny, cause on DMDWin you _can_ catch them.I just did a test C++ app in Windows (MsDev) .. and I do catch exceptions thrown by a null ptr reference. Which is what I was expecting to happen in D.
Jan 11 2008
Robert Fraser wrote:Sean Kelly wrote:Generating a stack trace within a signal handler would probably work, though it isn't guaranteed to. I'd say it depends on how the OS handles hardware signals. Throwing exceptions from signal handlers has the same problem. Seanphilippe.quesnel wrote:Any way to get Flectioned tracing them?Jarrett Billingsley Wrote:Segfaults in Windows pass through the Structured Exception Handling mechanism, as do many other hardware-level errors. It's the Windows response to signals in Unix. And DMD is nice enough to turn these into D exceptions for you. It sounds like GDC does its exception handling another way however, and does not.That's funny, cause on DMDWin you _can_ catch them.I just did a test C++ app in Windows (MsDev) .. and I do catch exceptions thrown by a null ptr reference. Which is what I was expecting to happen in D.
Jan 11 2008
ok, it seems this is a Windows vs 'Unix' difference... actually, more like a "Windows type" compiler vs GNU / 'Unix' compiler ! a simple C++ app that tries to write to a NULL ptr : On Windows : - compiled w. MsDev6 : the 'exception' is "catch"ed - compiled w. mingw32 C++ : seg faults (same w. cygwin) So depending on the compiler, the behaviour is different. AND .. same difference between GDC & DMD !! (as Jarrett mentionned) the same code (Windows again) .. + compiled w. gdc does not catch the 'exception', (segfault) + compiled w. dmd DOES catch the error niiiice .. NOT ;-) I'll have to look into this signal stuff .. time to read those other posts again ! thank you Phil
Jan 10 2008