This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: KeyboardInterrupt causes segmentation fault with threads
Type: Stage:
Components: Interpreter Core Versions: Python 2.4
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: anthonybaxter Nosy List: anthonybaxter, jeffstearns, mwh, tim.peters, zgoda
Priority: normal Keywords:

Created on 2005-03-18 05:18 by jeffstearns, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
thread_crash.py jeffstearns, 2005-03-18 05:18 Sample program demonstrating the crash
thread_crash2.py mwh, 2005-03-18 15:30 mwh's minimal? example
thread-exit-stuff.diff mwh, 2005-03-18 15:43 possible fix
thread-exit-stuff-2.diff mwh, 2005-03-28 11:53 fix mark II
Messages (19)
msg24679 - (view) Author: Jeff Stearns (jeffstearns) Date: 2005-03-18 05:18
The attached sample program crashes Python 2.4.1c1 with a 
segmentation fault if it is interupted.

I wrote a simple program which simulates multiple HTTP clients.

The program is mult-threaded.

It runs on Debian with a 2.6 kernel.

If the program is interrupted (via ^C), Python 2.4.1c1 takes a 
segmentation fault.

Investigation with gdb shows that the error occurs within 
PyEval_EvalFrame at line 1661 below.
It's executing an END_FINALLY bytecode.
The offending statement is
   v = POP();
The value of v is 0.
This is then passed to PyInt_Check(), which attempts to dereference 
a NULL pointer.


1659                    case END_FINALLY:
1660                            v = POP();
1661                            if (PyInt_Check(v)) {
1662                                    why = (enum why_code) 
PyInt_AS_LONG(v);
1663                                    assert(why != WHY_YIELD);
1664                                    if (why == WHY_RETURN ||
1665                                        why == WHY_CONTINUE)
1666                                            retval = POP();
1667                            }



#0  PyEval_EvalFrame (f=0x821cd04) at Python/ceval.c:1661
#1  0x080ae6bd in fast_function (func=0x4030df8d, 
pp_stack=0xbfffe85c, n=1, na=1076944740, nk=1079484852) at 
Python/ceval.c:3629
#2  0x080ae254 in call_function (pp_stack=0xbfffe85c, 
oparg=1076944740) at Python/ceval.c:3568
#3  0x080ac7a6 in PyEval_EvalFrame (f=0x8227d04) at Python/
ceval.c:2163
#4  0x080ad21e in PyEval_EvalCodeEx (co=0x4037e660, 
globals=0x4030df64, locals=0x4030df8d, args=0x40295c78, 
argcount=1, kws=0x0, kwcount=0, defs=0x0, defcount=0, 
closure=0x0)
    at Python/ceval.c:2730
#5  0x08105647 in function_call (func=0x4038a304, 
arg=0x40295c6c, kw=0x0) at Objects/funcobject.c:548
#6  0x0805c409 in PyObject_Call (func=0x8148088, 
arg=0x4030df64, kw=0x4030df64) at Objects/abstract.c:1751
#7  0x08062e38 in instancemethod_call (func=0x4038a304, 
arg=0x40295c6c, kw=0x4030df64) at Objects/classobject.c:2431
#8  0x0805c409 in PyObject_Call (func=0x8148088, 
arg=0x4030df64, kw=0x4030df64) at Objects/abstract.c:1751
#9  0x080ae0e7 in PyEval_CallObjectWithKeywords 
(func=0x4030df64, arg=0x4028702c, kw=0x405785a4) at Python/
ceval.c:3419
#10 0x0809101c in slot_tp_del (self=0x4057a1b4) at Objects/
typeobject.c:4818
#11 0x08086f93 in subtype_dealloc (self=0x4057a1b4) at Objects/
typeobject.c:669
#12 0x08062a4c in instancemethod_dealloc (im=0x4057857c) at 
Objects/classobject.c:2225
#13 0x080790a4 in dict_dealloc (mp=0x4056aacc) at Objects/
dictobject.c:734
#14 0x0805e544 in instance_dealloc (inst=0x40569dcc) at Objects/
classobject.c:687
#15 0x081042cb in frame_dealloc (f=0x8218f14) at Objects/
frameobject.c:418
#16 0x080dc1e9 in PyThreadState_Clear (tstate=0x81f9820) at 
Python/pystate.c:217
#17 0x080dbdf8 in PyInterpreterState_Clear (interp=0x8148048) at 
Python/pystate.c:93
#18 0x080dcef2 in Py_Finalize () at Python/pythonrun.c:408
#19 0x08055391 in Py_Main (argc=1, argv=0xbfffee14) at Modules/
main.c:504
#20 0x08054eeb in main (argc=1076944740, argv=0x4030df64) at 
Modules/python.c:23
msg24680 - (view) Author: Jeff Stearns (jeffstearns) Date: 2005-03-18 06:44
Logged In: YES 
user_id=660929

The bug also exists when Python is compiled with --with-pydebug:

% ./python2.4  -c 'import clientLoadSimulator; clientLoadSimulator.run(20)'
cccccccccccccCc.cCcCccCcc.CCC..CCC......C...........C.C..Traceback (most 
recent call last):
  File "<string>", line 1, in ?
  File "clientLoadSimulator.py", line 67, in run
    thread.join (1.0)
  File "/usr/local/lib/python2.4/threading.py", line 550, in join
    self.__block.wait(delay)
  File "/usr/local/lib/python2.4/threading.py", line 222, in wait
    _sleep(delay)
KeyboardInterrupt
[29492 refs]
Segmentation fault (core dumped)
msg24681 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 09:00
Logged In: YES 
user_id=6656

Can you try 2.3?  There were some changes in the area for 2.4.

I'll try to poke at it too.
msg24682 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 09:53
Logged In: YES 
user_id=6656

Does this always dump core for you?  When I ^C CVS HEAD running this 
a variety of nasty things happen, including one core dump and one "Fatal 
Python error: PyImport_GetModuleDict: no module dictionary!", but more 
often it's something like:

cccc^CTraceback (most recent call last):
  File "/Users/mwh/Desktop/thread_crash.py", line 67, in ?
    main(sys.argv)
  File "/Users/mwh/Desktop/thread_crash.py", line 64, in main
    run (20)
  File "/Users/mwh/Desktop/thread_crash.py", line 56, in run
    thread.start ()
  File "/Users/mwh/Source/python/dist/src/Lib/threading.py", line 418, in 
start
    _sleep(0.000001)    # 1 usec, to let the thread run (Solaris hack)
KeyboardInterrupt
Exception in thread Thread-4 (most likely raised during interpreter 
shutdown):
Traceback (most recent call last):
  File "/Users/mwh/Source/python/dist/src/Lib/threading.py", line 442, in 
__bootstrap
  File "/Users/mwh/Source/python/dist/src/Lib/threading.py", line 422, in 
run
  File "/Users/mwh/Desktop/thread_crash.py", line 23, in run
  File "/Users/mwh/Desktop/thread_crash.py", line 33, in runOnce
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 129, in 
urlopen
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 439, in 
build_opener
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 291, in 
add_handler
<class 'exceptions.TypeError'>: 'NoneType' object is not callable
Unhandled exception in thread started by 
Error in sys.excepthook:

Original exception was:
Exception in thread Thread-2 (most likely raised during interpreter 
shutdown):
Traceback (most recent call last):
  File "/Users/mwh/Source/python/dist/src/Lib/threading.py", line 442, in 
__bootstrap
  File "/Users/mwh/Source/python/dist/src/Lib/threading.py", line 422, in 
run
  File "/Users/mwh/Desktop/thread_crash.py", line 23, in run
  File "/Users/mwh/Desktop/thread_crash.py", line 33, in runOnce
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 129, in 
urlopen
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 439, in 
build_opener
  File "/Users/mwh/Source/python/dist/src/Lib/urllib2.py", line 291, in 
add_handler
<class 'exceptions.TypeError'>: 'NoneType' object is not callable
Unhandled exception in thread started by 
Error in sys.excepthook:

Original exception was:

with the last bit repeated a few times.

At a guess, it's some kind of interpreter tear-down horror.

Python 2.3 seems to behave much more sensibly.
msg24683 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 09:56
Logged In: YES 
user_id=6656

Oh, and I should say, I'm on OS X.
msg24684 - (view) Author: Jarek Zgoda (zgoda) Date: 2005-03-18 14:15
Logged In: YES 
user_id=92222

2.4 crashes also on Windows.
msg24685 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 14:52
Logged In: YES 
user_id=6656

And on linux too.

Gdb poking finds that the crash is in
socket._fileobject.close which is being called from
socket._fileobject.__del__ which is being called from  ...
PyThreadState_Clear, PyInterpreterState_Clear, Py_Finalize.
 So I still think it's some kind of tear-down horror.  Hmm.
msg24686 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 14:53
Logged In: YES 
user_id=6656

Duh, most of that was in the original report :)
msg24687 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 15:30
Logged In: YES 
user_id=6656

Chop chop chop.  Attached seems fairly minimal.  It's
something to do with exception handling in __del__ methods
that are called during interpreter tear down.
msg24688 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-18 15:43
Logged In: YES 
user_id=6656

Can you try the attached patch?
msg24689 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2005-03-18 21:38
Logged In: YES 
user_id=31435

I'm thinking maybe we should rename .setDaemon() 
to .generateRandomShutdownSegfaults() -- pretty much the 
same thing in practice!  Unless/until teardown is rewritten to 
be purely gc-based, asking a thread to keep running while 
the interpreter is destroying itself is going to be vulnerable.
msg24690 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-19 10:29
Logged In: YES 
user_id=6656

Well, sure.  However, the attached patch makes at least some of them go 
away; it also makes this comment from Py_Finalize:

	/* Now we decref the exception classes.  After this point nothing
	   can raise an exception.  That's okay, because each Fini() method
	   below has been checked to make sure no exceptions are ever
	   raised.
	*/
less hilariously inaccurate.  I'm not saying it's anything like a thorough fix.

I'm away for a week from about five minutes time, so if you like it, check it 
in yourself, please.
msg24691 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-27 21:21
Logged In: YES 
user_id=6656

Tim, I'd like to check this in.  You get a few days to object :)
msg24692 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2005-03-28 00:43
Logged In: YES 
user_id=31435

Yup, I agree it's an improvement.  Sorry I didn't have time to 
look at it last week (was at PyCon all day 7 days straight).
msg24693 - (view) Author: Anthony Baxter (anthonybaxter) (Python triager) Date: 2005-03-28 08:39
Logged In: YES 
user_id=29957

This patch won't compile for me on the 2.4 branch or the
trunk - there's no PyExceptionClass_Check defined that I can
find in the codebase, nor can I find anything that looks
like this anywhere. 
msg24694 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2005-03-28 11:53
Logged In: YES 
user_id=6656

Oh, pig.  Here's the patch with the irrelevant stuff from my new-style 
exceptions work chopped out (I should check that in soon, too I guess).
msg24695 - (view) Author: Anthony Baxter (anthonybaxter) (Python triager) Date: 2005-03-28 15:15
Logged In: YES 
user_id=29957

This patch applies, and seems to work. I can't see any
reasons for it to _not_ go into 2.4.1 final, unless someone
else can see a reason to avoid it, I'll check it in, in the
morning.
msg24696 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2005-03-28 19:12
Logged In: YES 
user_id=31435

Note that I already marked the patch as Accepted.

Re-assigning to Anthony, since he said he'll check it in.
msg24697 - (view) Author: Anthony Baxter (anthonybaxter) (Python triager) Date: 2005-03-29 13:36
Logged In: YES 
user_id=29957

Checked in on 2.4 branch and on trunk.
History
Date User Action Args
2022-04-11 14:56:10adminsetgithub: 41713
2005-03-18 05:18:03jeffstearnscreate