Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
July 19, 2013 GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
I am trying to throw exceptions in gtk signal handlers, but I am greeted with segfaults. What's the cause and are there solutions? (DMD 2.063.2 on Linux x86-64) Here is some reduced code: import gtk.Main; import gtk.MainWindow; import gdk.Event; import gtk.Widget; class TestWindow : MainWindow { this(string a) { super(a); this.addOnButtonPress(&click); } bool click(Event, Widget) { throw new Exception(""); } } int main(string[] args) { try { Main.init(args); auto win = new TestWindow("bla"); win.showAll(); Main.run(); return 0; } catch (Exception e) { writeln (e.msg); return 1; } } In gdb I get this (line numbers not matching with above example): Program received signal SIGSEGV, Segmentation fault. 0x00000000010f0b60 in rt.deh2.terminate() () (gdb) backtrace #0 0x00000000010f0b60 in rt.deh2.terminate() () #1 0x00000000010d538d in _d_throwc () #2 0x00000000010bdbcf in main.TestWindow.click() (this=0x7ffff7f25800, _param_1=0x7ffff7f25800, _param_0=0x7ffff7f23c80) at main.d:589 #3 0x0000000000e4dca3 in gtk.Widget.Widget.callBackButtonPress() (widgetStruct=0x16b9190, event=0x17dd5d0, _widget=0x7ffff7f25800) at gtk/Widget.d:693 #4 0x0000003f41385178 in ?? () from /usr/lib64/libgtk-3.so.0 #5 0x0000003ebce114f2 in g_closure_invoke () from /usr/lib64/libgobject-2.0.so.0 #6 0x0000003ebce22501 in ?? () from /usr/lib64/libgobject-2.0.so.0 #7 0x0000003ebce2ab4e in g_signal_emit_valist () from /usr/lib64/libgobject-2.0.so.0 #8 0x0000003ebce2b002 in g_signal_emit () from /usr/lib64/libgobject-2.0.so.0 #9 0x0000003f414b299f in ?? () from /usr/lib64/libgtk-3.so.0 #10 0x0000003f4138314b in ?? () from /usr/lib64/libgtk-3.so.0 #11 0x0000003f41384e01 in gtk_main_do_event () from /usr/lib64/libgtk-3.so.0 #12 0x0000003f40a4b372 in ?? () from /usr/lib64/libgdk-3.so.0 #13 0x0000003ebca4dbd3 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 #14 0x0000003ebca4ded8 in ?? () from /usr/lib64/libglib-2.0.so.0 #15 0x0000003ebca4e3ba in g_main_loop_run () from /usr/lib64/libglib-2.0.so.0 #16 0x0000003f413841bd in gtk_main () from /usr/lib64/libgtk-3.so.0 #17 0x0000000000d00747 in gtk.Main.Main.run() () at gtk/Main.d:366 #18 0x00000000010bbf3d in D main (args=...) at main.d:60 #19 0x00000000010d6038 in rt.dmain2._d_run_main() () #20 0x00000000010d5b6a in rt.dmain2._d_run_main() () #21 0x00000000010d6088 in rt.dmain2._d_run_main() () #22 0x00000000010d5b6a in rt.dmain2._d_run_main() () #23 0x00000000010d5b26 in _d_run_main () #24 0x00000000010d5973 in main () (gdb) disassemble Dump of assembler code for function _D2rt4deh29terminateFZv: 0x00000000010f0b5c <+0>: push %rbp 0x00000000010f0b5d <+1>: mov %rsp,%rbp => 0x00000000010f0b60 <+4>: hlt 0x00000000010f0b61 <+5>: pop %rbp 0x00000000010f0b62 <+6>: retq End of assembler dump. -- Marco |
July 19, 2013 Re: GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marco Leise | Am Fri, 19 Jul 2013 11:10:04 +0200 schrieb Marco Leise <Marco.Leise@gmx.de>: dav1d gave me advice on rebuilding druntime with debug symbols. That lead me to this "GitHub" stack trace: https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L104 https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L201 https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L246 ... back into my code where I throw the exception. -- Marco |
July 19, 2013 Re: GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marco Leise | Am Fri, 19 Jul 2013 11:47:41 +0200 schrieb Marco Leise <Marco.Leise@gmx.de>: > Am Fri, 19 Jul 2013 11:10:04 +0200 > schrieb Marco Leise <Marco.Leise@gmx.de>: > > dav1d gave me advice on rebuilding druntime with debug symbols. That lead me to this "GitHub" stack trace: > > https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L104 https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L201 https://github.com/D-Programming-Language/druntime/blob/v2.063.2/src/rt/deh2.d#L246 ... back into my code where I throw the exception. dav1d also told me to watch the DConf 2013 presentation of Higgs where a similar problem with asserts in JIT generated code occurred. It turns out that what Walter explained is the key here, too. All my libraries are compiled without frame pointers, so the simple stack unwinding that D uses fails there. I recompiled glib and gtk+ with -fno-omit-frame-pointer specifically and from now on exception handling works again. Additional info on stack unwinding in the absence of a frame pointer: http://www.yosefk.com/blog/getting-the-call-stack-without-a-frame-pointer.html -- Marco |
July 19, 2013 Re: GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marco Leise | Am Fri, 19 Jul 2013 12:38:45 +0200
schrieb Marco Leise <Marco.Leise@gmx.de>:
> It turns out that what Walter explained is the
> key here, too. All my libraries are compiled without frame
> pointers, so the simple stack unwinding that D uses fails
> there. I recompiled glib and gtk+ with -fno-omit-frame-pointer
> specifically and from now on exception handling works again.
Would be nice to know if this is working with gdc or ldc. In theory it should work as we use gcc's exception handling/stack unwinding so it's probably a dmd bug.
Slightly off topic, but maybe interesting:
Things can get really nasty if the GCC backend somehow decided
a function is nothrow and you throw from there. Unless GTK uses some
special __nothrow__ attributes that shouldn't happen in C, but I've seen
D code that throws from @nothrow functions and at least on ARM that
crashes... Might be a gdc bug or a problem with the D language
specification.
|
July 22, 2013 Re: GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Pfau | Am Fri, 19 Jul 2013 21:43:38 +0200 schrieb Johannes Pfau <nospam@example.com>: > Am Fri, 19 Jul 2013 12:38:45 +0200 > schrieb Marco Leise <Marco.Leise@gmx.de>: > > Would be nice to know if this is working with gdc or ldc. In theory it should work as we use gcc's exception handling/stack unwinding so it's probably a dmd bug. That's good to know. Is it possible to port that code into DMD ? How many C libraries do you think are prepared for exceptions ? They might have to clean up memory or system resources. > Slightly off topic, but maybe interesting: > Things can get really nasty if the GCC backend somehow decided > a function is nothrow and you throw from there. Unless GTK uses some > special __nothrow__ attributes that shouldn't happen in C, but I've seen > D code that throws from @nothrow functions and at least on ARM that > crashes... Might be a gdc bug or a problem with the D language > specification. If with @nothrow you mean the nothrow keyword, it has no value for compiler backends, because assert errors can be thrown anyways. But I probably misunderstood you. -- Marco |
July 23, 2013 Re: GktD: exceptions in handlers cause segfaults. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marco Leise | Am Mon, 22 Jul 2013 19:28:10 +0200 schrieb Marco Leise <Marco.Leise@gmx.de>: > Am Fri, 19 Jul 2013 21:43:38 +0200 > schrieb Johannes Pfau <nospam@example.com>: > > > Am Fri, 19 Jul 2013 12:38:45 +0200 > > schrieb Marco Leise <Marco.Leise@gmx.de>: > > > > Would be nice to know if this is working with gdc or ldc. In theory it should work as we use gcc's exception handling/stack unwinding so it's probably a dmd bug. > > That's good to know. Is it possible to port that code into DMD ? Probably not. It's implemented in libgcc and I don't know if it's tied to the compiler code gen. Porting is probably not possible because of the license. GCC's exception handling also has its own problems: For example we don't implement exception chaining right now. I just had another look at this and my last statement was not 100% accurate. GCC uses unwind tables instead of frame pointers so it can indeed work without frame pointers. But for C unwind tables are not generated by default unless -fexceptions is used. Interestingly enough it always worked for me ;-) > How many C libraries do you think are prepared for exceptions ? They might have to clean up memory or system resources. Probably very few. I was only talking from the compiler/codegen point of view but any C library that doesn't explicitly allow throwing exceptions probably won't work. > > > If with @nothrow you mean the nothrow keyword, it has no value for compiler backends, because assert errors can be thrown anyways. But I probably misunderstood you. Yeah well that's the general perception in the D community. But we need an authoritative statement here. According to TDPL, chapter 9.4 page 307: "Essentially Throwable is considered unrecoverable, so the compiler is relieved of the responsibility of "thinking" of what should happen in case of an exception and consequently _optimizes code under the assumption that nothing is thrown_." That's probably why Iain implemented it so that we directly map nothrow to gcc attribute(__nothrow__). However, I think this statement is supposed to talk about skipping destructors not necessarily unwinding. I don't really have a strong opinion here but according to Walter the backend can optimize quite a lot if it knows for sure that a function can't throw. As asserts can be optimized away anyway it might be useful to rewrite throw(Error) statements in nothrow functions to simply dump a stack trace and message to the console instead of proper exception handling. But as I said I don't have a string opinion here. |
Copyright © 1999-2021 by the D Language Foundation