Issue 11321: 9th import of module _pickle always crashes (original) (raw)

Created on 2011-02-25 15:51 by palm.kevin, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (11)

msg129384 - (view)

Author: Palm Kevin (palm.kevin)

Date: 2011-02-25 15:51

Please have a look to the following app:

#include "Python.h"

main(int argc, char **argv) { int i; printf("START\n"); for(i = 0; i < 20; i++){ Py_Initialize();

printf("Try import #%i ...", i);
PyRun_SimpleString("import _pickle\n");

printf("SUCCESS\n");
Py_Finalize();

} printf("END\n"); }

If I run that app (Linux), then I get the following output:

START Try import #0 ...SUCCESS Try import #1 ...SUCCESS Try import #2 ...SUCCESS Try import #3 ...SUCCESS Try import #4 ...SUCCESS Try import #5 ...SUCCESS Try import #6 ...SUCCESS Try import #7 ...SUCCESS Segmentation fault

It systematically crashes on the 9th call ... Does anybody know the reason of this segmentation fault problem??

msg129622 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2011-02-27 13:05

I can definitely confirm that one:

~/devel/py3k$ gcc -I/usr/local/include/python3.3m -o .c -L/usr/local/lib/python3.3 -lpython3.3m -lm -lpthread -ldl -lutil -rdynamic ~/devel/py3k$ ./issue11321 START Try import #0 ...SUCCESS Try import #1 ...SUCCESS Try import #2 ...SUCCESS Try import #3 ...SUCCESS Try import #4 ...SUCCESS Try import #5 ...SUCCESS Try import #6 ...SUCCESS Try import #7 ...SUCCESS Segmentation fault

I can also confirm that it isn't a regression w.r.t 3.1:

~/devel/py3k$ gcc -I/usr/include/python3.1 -o .c -L/usr/lib/python3.1 -lpython3.1 -lm -lpthread -ldl -lutil -rdynamic ~/devel/py3k$ ./issue11321 START Try import #0 ...SUCCESS Try import #1 ...SUCCESS Try import #2 ...SUCCESS Try import #3 ...SUCCESS Try import #4 ...SUCCESS Try import #5 ...SUCCESS Try import #6 ...SUCCESS Try import #7 ...SUCCESS Segmentation fault

It is, however, a regression from the 2.x line (where, presumably, cPickle simply never got reinitialised)

msg129623 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2011-02-27 13:17

I haven't worked out where the error is happening yet, but the 13 allocated static variables and the complete lack of a module cleanup function aren't going to be helping matters.

msg129624 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2011-02-27 13:43

Here's a sample stack trace of it blowing up:

Program received signal SIGSEGV, Segmentation fault. 0x0000000000479404 in type_dealloc (type=0x7ffff6a82f20) at Objects/typeobject.c:2523 2523 _PyObject_GC_UNTRACK(type);

(gdb) bt #0 0x0000000000479404 in type_dealloc (type=0x7ffff6a82f20) at Objects/typeobject.c:2523 #1 0x0000000000465a2b in dict_dealloc (mp=0x8f61b0) at Objects/dictobject.c:1020 #2 0x00000000004e43c8 in _PyImport_FixupExtensionUnicode (mod=0x7ffff7f68ef0, name=0x7fffffffcd40 "_pickle", filename=0x7ffff7f12570) at Python/import.c:611 #3 0x00000000004e7fcf in _PyImport_LoadDynamicModule (name=0x7fffffffcd40 "_pickle", pathname=0x7fffffffbc70 "/usr/local/lib/python3.3/lib-dynload/_pickle.cpython-33m.so", fp=) at ./Python/importdl.c:85 #4 0x00000000004e5f79 in import_submodule (mod=0x796b20, subname=0x7fffffffcd40 "_pickle", fullname=0x7fffffffcd40 "_pickle") at Python/import.c:2894 #5 0x00000000004e61ef in load_next (mod=0x796b20, altmod=, p_name=, buf=0x7fffffffcd40 "pickle", p_buflen=0x7fffffffcd38) at Python/import.c:2706 #6 0x00000000004e6931 in import_module_level (name=0x0, globals=0x922060, locals=, fromlist=0x796b20, level=) at Python/import.c:2422 #7 0x00000000004e6e74 in PyImport_ImportModuleLevel (name=0x7ffff7e6c550 "pickle", globals=0x922060, locals=0x922060, fromlist=0x796b20, level=) at Python/import.c:2474 #8 0x00000000004c642b in builtin___import (self=, args=, kwds=) at Python/bltinmodule.c:167 #9 0x000000000042c897 in PyObject_Call (func=0x7ffff7edf8c0, arg=0x8e79e0, kw=0xa2e79) at Objects/abstract.c:2149 #10 0x00000000004c6c73 in PyEval_CallObjectWithKeywords (func=0x7ffff7edf8c0, arg=0x7ffff7e85ef0, kw=0xa2e79) at Python/ceval.c:3739 #11 0x00000000004ca6de in PyEval_EvalFrameEx (f=0xae4490, throwflag=) at Python/ceval.c:2316 #12 0x00000000004cf343 in PyEval_EvalCodeEx (_co=0x7ffff7ea5690, globals=, locals=, args=0x0, argcount=, kws=, kwcount=0, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0) at Python/ceval.c:3295 #13 0x00000000004cf5db in PyEval_EvalCode (co=0x7ffff6a82f20, globals=0x8e79e0, locals=0xa2e79) at Python/ceval.c:761 #14 0x0000000000419c7e in run_mod (command=, flags=) at Python/pythonrun.c:1769 #15 PyRun_StringFlags (command=, flags=) at Python/pythonrun.c:1703 #16 PyRun_SimpleStringFlags (command=, flags=) at Python/pythonrun.c:1276 #17 0x0000000000415c41 in main ()

So _pickle itself doesn't seem to be dying, but it is eventually leaving things in a bad state so that the next time around, the import machinery blows up. Note that switching to a different module (e.g. "_struct") eliminates the segfault.

msg129626 - (view)

Author: Andreas Stührk (Trundle) *

Date: 2011-02-27 14:03

It's because the _pickle module doesn't incref Pickler_Type and Unpickler_Type before calling PyModule_AddObject() (which steals a reference).

The attached patch fixes the issue.

msg129670 - (view)

Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer)

Date: 2011-02-27 23:34

The patch looks good. It may also fix , which fails in a similar fashion

msg129674 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2011-02-28 00:24

While Andreas's patch does indeed prevent the crash, there is something more going on here.

I modified his patch to print out the reference counts immediately after the new INCREF commands.

With the INCREF commands commented out, it looks like this:

~/devel/py3k$ ./issue113213.3 START Try import #0 ...Initialising _pickle Pickler type references: 10 Unpickler type references: 8 Module initialised SUCCESS Try import #1 ...Initialising _pickle Pickler type references: 10 Unpickler type references: 8 Module initialised SUCCESS Try import #2 ...Initialising _pickle Pickler type references: 9 Unpickler type references: 7 Module initialised SUCCESS Try import #3 ...Initialising _pickle Pickler type references: 8 Unpickler type references: 6 Module initialised SUCCESS Try import #4 ...Initialising _pickle Pickler type references: 7 Unpickler type references: 5 Module initialised SUCCESS Try import #5 ...Initialising _pickle Pickler type references: 6 Unpickler type references: 4 Module initialised SUCCESS Try import #6 ...Initialising _pickle Pickler type references: 5 Unpickler type references: 3 Module initialised SUCCESS Try import #7 ...Initialising _pickle Pickler type references: 4 Unpickler type references: 2 Module initialised SUCCESS Try import #8 ...Initialising _pickle Pickler type references: 3 Unpickler type references: 1 Module initialised Segmentation fault

Note that it does the right thing the first time Py_Finalize is called, but the reference counts start going down after that.

When the INCREF is included, the count goes up initially and then levels out.

So I believe the simple patch is just masking the problem instead of fixing it. The correct answer is to follow the documentation and implement the module finalisation protocol for _pickle (i.e. move all the static globals into the module struct and implement module traversal and finalisation functions).

msg129675 - (view)

Author: Andreas Stührk (Trundle) *

Date: 2011-02-28 01:05

That initial increase you can see happens because the module's dict is copied in _PyImport_FixupExtensionUnicode().

msg129678 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2011-02-28 01:31

Looking at the example of _struct.c, I'll withdraw my objection to the patch. The segfault is due to the attempt to destroy a statically allocated type object, and the only viable solution to that is to ensure the reference count never drops to 0, even during Py_Finalize.

I also created to cover the fact that _pickle really shouldn't be stashing things in static globals now that a better alternative is available.

msg140458 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2011-07-15 19:03

New changeset 1ae0b7b8de0b by Antoine Pitrou in branch '3.2': Issue #11321: Fix a crash with multiple imports of the _pickle module when http://hg.python.org/cpython/rev/1ae0b7b8de0b

New changeset 6674272754da by Antoine Pitrou in branch 'default': Issue #11321: Fix a crash with multiple imports of the _pickle module when http://hg.python.org/cpython/rev/6674272754da

msg140459 - (view)

Author: Antoine Pitrou (pitrou) * (Python committer)

Date: 2011-07-15 19:04

Should be fixed now, thank you!

History

Date

User

Action

Args

2022-04-11 14:57:13

admin

set

github: 55530

2011-07-15 19:04:09

pitrou

set

status: open -> closed
versions: - Python 3.1
messages: +

resolution: fixed
stage: resolved

2011-07-15 19:03:25

python-dev

set

nosy: + python-dev
messages: +

2011-03-25 02:05:30

vstinner

set

nosy: + vstinner

2011-02-28 01:31:16

ncoghlan

set

nosy: + loewis

messages: +
versions: + Python 3.3

2011-02-28 01:15:21

ncoghlan

link

issue9197 superseder

2011-02-28 01:05:34

Trundle

set

nosy:brett.cannon, amaury.forgeotdarc, ncoghlan, pitrou, alexandre.vassalotti, Trundle, palm.kevin
messages: +

2011-02-28 00:24:24

ncoghlan

set

nosy:brett.cannon, amaury.forgeotdarc, ncoghlan, pitrou, alexandre.vassalotti, Trundle, palm.kevin
messages: +

2011-02-27 23:34:26

amaury.forgeotdarc

set

nosy: + amaury.forgeotdarc
messages: +

2011-02-27 14:03:35

Trundle

set

files: + issue11321.patch

nosy: + Trundle
messages: +

keywords: + patch

2011-02-27 13:43:35

ncoghlan

set

nosy:brett.cannon, ncoghlan, pitrou, alexandre.vassalotti, palm.kevin
messages: +

2011-02-27 13:17:56

ncoghlan

set

nosy:brett.cannon, ncoghlan, pitrou, alexandre.vassalotti, palm.kevin
messages: +

2011-02-27 13:05:25

ncoghlan

set

nosy:brett.cannon, ncoghlan, pitrou, alexandre.vassalotti, palm.kevin
messages: +

2011-02-26 17:28:46

eric.araujo

set

nosy: + alexandre.vassalotti, brett.cannon, ncoghlan, pitrou

2011-02-25 15:52:09

palm.kevin

set

versions: + Python 3.1

2011-02-25 15:51:21

palm.kevin

create