Page MenuHome

Retitled: Print a python backtrace to stderr on segfault
ClosedPublic

Authored by Daniel Bailey (danieljabailey) on Aug 3 2020, 9:13 PM.

Details

Reviewers
Campbell Barton (campbellbarton)
Group Reviewers
Python API
Summary

Old title: Added a segfault handler which is active during python execution to print a python backtrace on segfault

When users run into problems such as the one described in T77038, Blender will crash, and will write some not-particularly-helpful information to a file.
In this scenario, some user python code has caused blender to crash because the user has written some bad code that causes blender to segfault.
When this happens, it is very tricky for the user to isolate exactly where the problem is in their python code. I want to fix this.

This patch adds a segfault handler that can print a python backtrace upon a segfault, which makes it much easier for the user to find the problem in their code.
Ideally, I would like this to be presented to the user in a small dialog window when the crash happens, but for now it just prints it to stderr.

Previously I would get this output on a segfault:

Writing: /tmp/test_segfault.crash.txt
fish: “../build_linux_debug/bin/blender” terminated by signal SIGSEGV (Address boundary error)
daniel@dan-l13 ~/b/blender (master) [SIGSEGV]>

This patch enables me now to have some clue of where the problem occurred, as it prints this instead:

Segfault at 0x70 during execution of python code.
This could be either a blender bug or a user-provided python bug.
Stack trace (most recent call first):
  File "/home/daniel/Downloads/test_segfault.blend/test.py", line 16 in handler
Writing: /tmp/test_segfault.crash.txt
fish: “../build_linux_debug/bin/blender” terminated by signal SIGSEGV (Address boundary error)
daniel@dan-l13 ~/b/blender (master) [SIGSEGV]>

Diff Detail

Repository
rB Blender

Event Timeline

I like the added information, it can be quite useful when figuring out what the cause of a crash could be.

@Daniel Bailey (danieljabailey) Have you done any performance measurements? For example, do you see any drop in viewport FPS when playing back the animation of Hi, my name is Amy?

  • While useful, it seems excessive to enable on every call to a Python function for what is a fairly specialized debugging feature even if the performance overhead is not significant, it's going to add _some_ overhead which I'd rather avoid. (every panel redraw for every frame change, every operator poll function for every button to check if it should be greyed out... for example),
  • To avoid impacting performance for users - we could be enabled only in debug builds to avoid slowing down release builds for a very spesific debugging options, seeing as the back-traces aren't likely to be as useful in release builds.
  • Having to add this around every PyObject_Call* isn't convenient, by the looks of things there are many other places this should be added, checking source/ there are over 50 calls to PyObject_Call.* functions. Many of these look like they would need the segfault handlers surrounding them if this patch is to cover all calls into Python.

Are there any reasons not to use Blender's existing sig_handle_crash for this? (see ./source/creator/creator_signals.c).

We could add a check for Python being active, including the stack trace when it is (see PyC_IsInterpreterActive).

Campbell Barton (campbellbarton) requested changes to this revision.Aug 5 2020, 6:02 AM
Campbell Barton (campbellbarton) added inline comments.
source/blender/makesrna/intern/rna_wm.c
43

Including other modules internal headers should be avoided, instead use BPY_extern.h

source/blender/python/intern/bpy_segfault_handler.c
53–63
  • strdup use here seems unnecessary, the Py_DECREF(funcname); can be moved after the print.
  • Not sure why PyUnicode_AsEncodedString is used here, _PyUnicode_AsString is used elsewhere for this purpose.
  • If PyUnicode_AsEncodedString is needed, "strict" encoding increases the chance there will be an encoding error while printing the stack. Wouldn't "ignore" or "surrogateescape" make more sense?
source/blender/python/intern/bpy_segfault_handler.h
24–25

For public functions, use common prefix BPY_ in this case (matching other functions in BPY_extern.h).

This revision now requires changes to proceed.Aug 5 2020, 6:02 AM

@Campbell Barton (campbellbarton) Thanks for the review, some helpful suggestions :)

On one point though, you said this:

To avoid impacting performance for users - we could be enabled only in debug builds to avoid slowing down release builds for a very spesific debugging options, seeing as the back-traces aren't likely to be as useful in release builds.

If this will only ever make it into debug builds then there's no point in me taking this any further. The point of this was to be able to get backtrace information in a normal release build. If I have to build my own debug blender to get this stuff then it's not really that useful to me (perhaps it would be to a blender dev, but I want this for writing python scripts as a user)
So with that in mind I will endeavor to make sure that this has no performance overhead (or at worst, a trivially small overhead) so that it can be included in normal release builds.

I will tweak the code as suggested to minimise overhead and use @Sybren A. Stüvel (sybren) 's suggested test file to make sure it is still quick :)

Thanks.
Dan.

Daniel Bailey (danieljabailey) retitled this revision from Added a segfault handler which is active during python execution to print a python backtrace on segfault to Retitled: Print a python backtrace to stderr on segfault.
Daniel Bailey (danieljabailey) edited the summary of this revision. (Show Details)

This new diff should include all the recommended changes,
that python string conversion function did indeed work, the code looks much cleaner now :)

I haven't done any performance checking, but since this is now chained from the usual segfault handler, the only time where any new code from this patch will run is during a segfault. At this point blender is about to crash so I'm sure performance isn't a big issue there :D

This should also resolve my worry about how this works on windows, as presumably the normal segfault handler works on windows too.

Thanks, committed rBe9c4325515ae: Python: include Python stack trace in the crash log

Note that I've moved the crash output to the *.crash.txt file written by the segfault handler, as this is sometimes included in bug reports and accessible even when the console isn't shown.

This revision is now accepted and ready to land.Aug 6 2020, 7:51 AM

Awesome.
Thankyou everyone.
My first ever contribution to blender is in! Yay! \o/
:D