Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Conversation

Marenz
Copy link

@Marenz Marenz commented May 28, 2015

This commit allows exceptions from Fibers to be completely uncaught thus
causing a termination of the program and, depending on the configuration,
creation of a core dump.

An attached debugger can then be used to properly investigate the status of the
program at the time of the failure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make this the last parameter to avoid breaking code.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an alternative I could also add two new c'tors with the same arguments as this one right now

@Marenz
Copy link
Author

Marenz commented May 29, 2015

Update:

  • Made new parameter the last one in the c'tor to avoid breaking code

This commit allows exceptions from Fibers to be completely uncaught thus
causing a termination of the program and, depending on the configuration,
creation of a core dump.

An attached debugger can then be used to properly investigate the status of the
program at the time of the failure.
@Marenz
Copy link
Author

Marenz commented May 29, 2015

The failed test seems to be unrelated to my PR:

std.exception.ErrnoException@std\stdio.d(1559): Could not create temporary file with tmpfile() (No error)
----------------
0x004CDD63 in @safe shared(core.stdc.stdio._iobuf)* std.exception.__T12errnoEnforceTPOS4core4stdc5stdio6_iobufVAyaa11_7374645c737464696f2e64Vki1559Z.errnoEnforce(shared(core.stdc.stdio._iobuf)*, lazy immutable(char)[])
0x00480072 in void std.stdio.__modtest()
The system cannot find the path specified.

@mathias-baumann-sociomantic

@MartinNowak I've been told I could hilight you to get more attention for this PR :)

@MartinNowak
Copy link
Member

This'll remove the final catch handler for the Fiber stacks. That's a bad idea, you're program will get halted b/c unwinding will likely fail, but it might also cause a memory corruption instead.
Also this renders the call(Rethrow rethrow) API non-working is some cases.
Are you trying to solve Issue 7018 – thrown Error from different thread should lead to program abort with this?

@mathias-baumann-sociomantic

I wasn't aware of the issue. My goal here is that an uncaught exception/error results in a core dump/program termination that leaves me with a backtrace within GDB (or the core dump) which allows me to investigate the state of the program, e.g. printing the variables the assert was checking etc.

Without this, it would just print a mostly unhelpful stack trace (because of missing line numbers) to the terminal and kill the fiber but keep running. When an assert fails I want to have my core dump from the assert that failed and not some location where we re-threw the exception/error.

I guess an alternative could be to do a call to abort(), though not sure where I would need to do that, probably inside _d_throwc

(I am Marenz)

@jpf91
Copy link
Contributor

jpf91 commented Aug 1, 2015

I'm not sure if what you want to do is actually possible. You do not get a core dump from uncaught errors. If you get one with these patches then it's because you crash the unwinder as you read out of the stack bounds, as @MartinNowak already said. However, I don't see how such a core dump would be helpful. A backtrace in the core dump wouldn't point at your assert or wherever you originally threw the error, it'd point at the crash in the unwinder AFAICS.

My goal here is that an uncaught exception/error results in a core dump/program termination
[...] call to abort() [...] probably inside _d_throwc

If you want to get the correct trace in GDB you'll have to abort at the throw location. But you can't know at the throw location if the error is "uncaught". You can only do one thing: You can make all asserts abort (_d_assert, see http://wiki.dlang.org/Runtime_Hooks). Or you might be able to make it abort for all errors. If the only thing you know about your exception is that it's "uncaught" you can't get more information than the builtin unwinder provides. (The GDC unwider BTW prints function names and line numbers if you build your code with -g). Most notably you can't get the stack frame, variables etc at the throw point in this case.

But if you just want to debug a concrete problem there might be simpler solutions. First of all even if the dmd stacktraces don't provide function names they should provide addresses. Then you can simply use addr2line to find the function. Or you simply set a breakpoint at _d_assert if you know it's a failing assert. Of course this won't work for "uncaught" exceptions in general.

@mathias-baumann-sociomantic

However, I don't see how such a core dump would be helpful. A backtrace in the core dump wouldn't point at your assert or wherever you originally threw the error, it'd point at the crash in the unwinder AFAICS.

That is not my experience though. I did get useful stack traces that did point at the place where the assert fails.

If you want to get the correct trace in GDB you'll have to abort at the throw location. But you can't know at the throw location if the error is "uncaught".

As far as I understand, _d_throwc runs through the stack trying to find handlers. If it can't find any, it calls terminate() which does the asm instruction hlt which I assume results in a core dump/abort. Which is exactly what I want. And this is also exactly the location that I need (it's one call further down in the stack from where the exception/error was thrown). So I don't see how your statement is correct here..

But if you just want to debug a concrete problem there might be simpler solutions.

I am more trying to find a generic useful behaviour in typical debug situations. I actually find it hard to believe that something like this hasn't been implemented so far. It feels like such a intuitive and normal thing. Get assert -> abort. Normal c++ behaviour. Normal c behaviour. And the most useful thing you can do.

@jpf91
Copy link
Contributor

jpf91 commented Aug 3, 2015

That is not my experience though. I did get useful stack traces that did point at the place where the assert fails.

And this is also exactly the location that I need (it's one call further down in the stack from where the exception/error was thrown). So I don't see how your statement is correct here..

Sorry, you're right. It looks like our unwinders are smart enough to recognize the end of the Fiber stack. So as you say the exception handling doesn't crash in the unwind process, it explicitly aborts as it can't find a top level exception handler (It doesn't find higher level druntime handlers as the corresponding functions are not on the fiber callstack).

I think this would still require some further thinking whether this is 100% safe and guaranteed by the language. AFAICS we don't use that 'abort' feature anywhere right now.

Another problem is that we print stack traces for asserts in normal programs. Doing something different in Fibers might be strange. We probably need an option to make uncaught exceptions core-dump in non-fiber programs as well.

I actually find it hard to believe that something like this hasn't been implemented so far. It feels like such a intuitive and normal thing. Get assert -> abort. Normal c++ behaviour. Normal c behaviour. And the most useful thing you can do.

You're probably starting a holy language-feature war here ;-) It does indeed make sense to stop programs at asserts. But some people prefer builtin unwinding instead of crashing (=>calling a debugger) as it provides a backtrace without a debugger (ask Walter what he thinks of GDB ;-). OTOH the fact that Errors can propagate through nothrow functions is confusing, sometimes doesn't work (unwinding through C functions) or requires extra work from compiler devs (ARM crashes when throwing anything from nothrow functions.).

So I'll leave this pull request up to the druntime maintainers. I think it would make most sense to:

  • never unwind when throwing non-exception Throwables, assert etc and abort instead. (Avoids the stupid unwind-through-nothrow functions schizophrenia). Or allow unwinding in debug mode, but at least disable it for release mode (Allows further optimization).
  • Add a druntime command line switch which switches between printing a stack trace for uncaught exceptions and abort.
  • Maybe do some debugger auto-detection if this is possible.

@mathias-baumann-sociomantic

Another problem is that we print stack traces for asserts in normal programs. Doing something different in Fibers might be strange. We probably need an option to make uncaught exceptions core-dump in non-fiber programs as well.

That would indeed be something I want, too. I just thought of this as the first step.

Add a druntime command line switch which switches between printing a stack trace for uncaught exceptions and abort.

Sounds good to me.

@Marenz
Copy link
Author

Marenz commented Apr 7, 2016

I did some digging and it seems what I want is almost possible with rt_trapExceptions.
I am closing this PR in favor of those two:

#1537
#1538

@Marenz Marenz closed this Apr 7, 2016
@Marenz Marenz deleted the fiberexc branch April 7, 2016 13:41
@zenixan
Copy link

zenixan commented Apr 8, 2016

,
On May 29, 2015 2:24 AM, "Mathias L. Baumann" [email protected]
wrote:

This commit allows exceptions from Fibers to be completely uncaught thus
causing a termination of the program and, depending on the configuration,
creation of a core dump.

An attached debugger can then be used to properly investigate the status
of the

program at the time of the failure.

You can view, comment on, or merge this pull request online at:

#1288
Commit Summary

  • Make catching of exceptions from Fibers optional

File Changes

Patch Links:


Reply to this email directly or view it on GitHub
#1288.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants