classification
Title: faulthandler prints tracebacks in reverse order
Type: behavior Stage:
Components: Extension Modules Versions: Python 3.3, Python 3.2
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: haypo, ncoghlan, pitrou
Priority: normal Keywords: patch

Created on 2012-04-24 22:17 by pitrou, last changed 2012-04-25 07:10 by haypo.

Files
File name Uploaded Description Edit
reverse_frames.patch pitrou, 2012-04-24 22:38 review
Messages (5)
msg159223 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-04-24 22:17
Python usually prints traceback from the outer to the inner function: the inner frame is printed last. But faulthandler prints the inner frame first and the outer frame last.
msg159227 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-04-24 22:38
Here is a patch.
msg159229 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2012-04-24 22:51
faulthandler has to be as simple as possible because Python internal state may be completly corrupted. faulthandler was written to display the traceback on bugs like invalid memory read or write. I chose to print the traceback as it is stored in memory (from the current frame to the bottom of the stack using f_back).

If the traceback is corrupted in the middle of the frame stack, faulthandler displays the first half of the traceback, whereas it would not display anything with your patch.

The number of frames is also limited to avoid unlimited loops. The internal state may be corrupted and I don't want to track already seen frames or something like that. With your patch, you may miss where the bug occurred if the stack contains more than 100 frames. The limit is hardcoded and cannot be changed at runtime yet.

I already seen a segfault while faulthandler was trying to display the traceback of a segfault, more than once :-)
msg159252 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2012-04-25 05:49
Victor's argument makes sense to me. What I'd be inclined to do is shout at the reader a bit in the traceback header by making it:

    Traceback (most recent call FIRST):

And put a comment in the source code with the gist of what Victor wrote above (i.e. internal state may be corrupted, we do the best we can with what we've got, and that means printing the traceback from the inside out)
msg159260 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2012-04-25 07:10
> Victor's argument makes sense to me. What I'd be inclined to do is shout at the reader a bit in the traceback header by making it:
>
>    Traceback (most recent call FIRST):

The output is something like:

Thread 0xf758d8d0:

 File "/home/edcjones/programs/python/Python-3.3.0a2/Lib/socket.py",
line 407 in create_connection
 File "/home/edcjones/programs/python/Python-3.3.0a2/Lib/imaplib.py",
line 236 in _create_socket
 File "/home/edcjones/programs/python/Python-3.3.0a2/Lib/imaplib.py",
line 1201 in _create_socket
...

"Thread 0xf758d8d0:" can be replaced with "Thread 0xf758d8d0 (most
recent call FIRST):".

A "reverse=False" parameter can be added to
faulthandler.dump_traceback() and
faulthandler.dump_tracebacks_later(). But I prefer to not add it to
faulthandler.enable() nor faulthandler.register() because
dump_traceback() is called from a signal handler. It may be surprising
to have an option on some functions but not on all functions.
History
Date User Action Args
2012-04-25 07:10:29hayposetmessages: + msg159260
2012-04-25 05:49:08ncoghlansetmessages: + msg159252
2012-04-24 22:51:14hayposetmessages: + msg159229
2012-04-24 22:38:12pitrousetfiles: + reverse_frames.patch

nosy: + ncoghlan
messages: + msg159227

keywords: + patch
2012-04-24 22:17:14pitroucreate