After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 677091 - Embedded Python C program segfaults in subsequent call after reinitialization
Embedded Python C program segfaults in subsequent call after reinitialization
Status: RESOLVED OBSOLETE
Product: pygobject
Classification: Bindings
Component: introspection
3.2.x
Other Linux
: Normal major
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on: 735206
Blocks:
 
 
Reported: 2012-05-30 12:00 UTC by Andrey Gursky
Modified: 2018-01-10 20:16 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
minimal example for problem demonstration (1.98 KB, text/x-csrc)
2012-05-30 12:00 UTC, Andrey Gursky
  Details
test script (289 bytes, text/x-python)
2012-05-30 12:01 UTC, Andrey Gursky
  Details
An update example (1.17 KB, text/x-csrc)
2012-06-10 12:17 UTC, Andrey Gursky
  Details
Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed (3.54 KB, patch)
2013-04-20 00:15 UTC, Simon Feltman
committed Details | Review
tests: Setup automake parallel test harness (3.28 KB, patch)
2014-09-13 06:52 UTC, Simon Feltman
none Details | Review
tests: Add test for multiple interpreter init and shutdowns (3.24 KB, patch)
2014-09-13 06:52 UTC, Simon Feltman
none Details | Review

Description Andrey Gursky 2012-05-30 12:00:17 UTC
Created attachment 215239 [details]
minimal example for problem demonstration

The minimal example illustrates the problem.

The output:
$ ./test_embed_python 
running embedded python...
 ------------ script end ----------
...done
running embedded python...
Segmentation fault

The script test.py:

#from gi.repository import GLib
#from gi.repository import Gtk
#from gi.repository import Cairo
#from gi.repository import Pango
from gi.repository import Gio

def call_python():
    print(" ------------ script end ----------")
    return 0
 
if __name__ == '__main__':
    call_python()

---------------------------------

Once at least one package from the gi.repository is imported, the embedded python fails to run it after the reinitialization (Py_Initialize/Finalize).
Comment 1 Andrey Gursky 2012-05-30 12:01:18 UTC
Created attachment 215240 [details]
test script
Comment 2 Andrey Gursky 2012-06-10 10:52:38 UTC
FYI: I'm using Debian Wheezy with python2.7 (2.7.3~rc2-2.1), pygobject (3.2.2-1).

Here is the backtrace:
running embedded python...
 ------------ script end ----------
[34268 refs]
...done
running embedded python...

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff79dcc27 in PyObject_GC_UnTrack (op=0xb3b880) at ../Modules/gcmodule.c:1428
1428	../Modules/gcmodule.c: No such file or directory.
(gdb) bt
  • #0 PyObject_GC_UnTrack
    at ../Modules/gcmodule.c line 1428
  • #1 _base_info_dealloc
    at /home/martin/debian/pkg-gnome/build-area/pygobject-3.2.2/gi/pygi-info.c line 35
  • #2 _Py_Dealloc
    at ../Objects/object.c line 2243
  • #3 frame_dealloc
    at ../Objects/frameobject.c line 458
  • #4 _Py_Dealloc
    at ../Objects/object.c line 2243
  • #5 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3264
  • #6 function_call
    at ../Objects/funcobject.c line 526
  • #7 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #8 instancemethod_call
    at ../Objects/classobject.c line 2578
  • #9 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #10 PyObject_CallFunctionObjArgs
    at ../Objects/abstract.c line 2760
  • #11 call_attribute
    at ../Objects/typeobject.c line 5441
  • #12 slot_tp_getattr_hook
    at ../Objects/typeobject.c line 5495
  • #13 PyObject_GetAttr
    at ../Objects/object.c line 1191
  • #14 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2256
  • #15 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #16 fast_function
    at ../Python/ceval.c line 4117
  • #17 call_function
    at ../Python/ceval.c line 4042
  • #18 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #19 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #20 PyEval_EvalCode
    at ../Python/ceval.c line 667
  • #21 PyImport_ExecCodeModuleEx
    at ../Python/import.c line 681
  • #22 load_source_module
    at ../Python/import.c line 1018
  • #23 load_module
    at ../Python/import.c line 1822
  • #24 import_submodule
    at ../Python/import.c line 2595
  • #25 ensure_fromlist
    at ../Python/import.c line 2506
  • #26 import_module_level
    at ../Python/import.c line 2174
  • #27 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #28 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #29 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #30 do_call
    at ../Python/ceval.c line 4236
  • #31 call_function
    at ../Python/ceval.c line 4044
  • #32 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #33 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #34 fast_function
    at ../Python/ceval.c line 4117
  • #35 call_function
    at ../Python/ceval.c line 4042
  • #36 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #37 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #38 function_call
    at ../Objects/funcobject.c line 526
  • #39 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #40 instancemethod_call
    at ../Objects/classobject.c line 2578
  • #41 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #42 call_function_tail
    at ../Objects/abstract.c line 2561
  • #43 PyObject_CallMethod
    at ../Objects/abstract.c line 2638
  • #44 load_module
    at ../Python/import.c line 1877
  • #45 import_submodule
    at ../Python/import.c line 2595
  • #46 ensure_fromlist
    at ../Python/import.c line 2506
  • #47 import_module_level
    at ../Python/import.c line 2174
  • #48 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #49 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #50 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #51 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #52 PyEval_CallObjectWithKeywords
    at ../Python/ceval.c line 3890
  • #53 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2333
  • #54 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #55 PyEval_EvalCode
    at ../Python/ceval.c line 667
  • #56 PyImport_ExecCodeModuleEx
    at ../Python/import.c line 681
  • #57 load_source_module
    at ../Python/import.c line 1018
  • #58 load_module
    at ../Python/import.c line 1822
  • #59 import_submodule
    at ../Python/import.c line 2595
  • #60 load_next
    at ../Python/import.c line 2415
  • #61 import_module_level
    at ../Python/import.c line 2136
  • #62 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #63 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #64 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #65 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #66 call_function_tail
    at ../Objects/abstract.c line 2561
  • #67 PyObject_CallFunction
    at ../Objects/abstract.c line 2585
  • #68 PyImport_Import
    at ../Python/import.c line 2773
  • #69 call_python
    at test_embed_python.c line 37
  • #70 main
    at test_embed_python.c line 89

Comment 3 Andrey Gursky 2012-06-10 12:16:14 UTC
I've noticed, it is enough just to import the script, not to call it at all.

The updated minimal example and backtrace are attached.
Comment 4 Andrey Gursky 2012-06-10 12:17:46 UTC
Created attachment 216053 [details]
An update example
Comment 5 Andrey Gursky 2012-06-10 12:18:50 UTC
Backtrace:

running embedded python...
[36161 refs]
...done
running embedded python...

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff79dcc27 in PyObject_GC_UnTrack (op=0xb60da8) at ../Modules/gcmodule.c:1428
1428	../Modules/gcmodule.c: No such file or directory.
(gdb) bt
  • #0 PyObject_GC_UnTrack
    at ../Modules/gcmodule.c line 1428
  • #1 _base_info_dealloc
    at /home/martin/debian/pkg-gnome/build-area/pygobject-3.2.2/gi/pygi-info.c line 35
  • #2 _Py_Dealloc
    at ../Objects/object.c line 2243
  • #3 frame_dealloc
    at ../Objects/frameobject.c line 458
  • #4 _Py_Dealloc
    at ../Objects/object.c line 2243
  • #5 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3264
  • #6 function_call
    at ../Objects/funcobject.c line 526
  • #7 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #8 instancemethod_call
    at ../Objects/classobject.c line 2578
  • #9 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #10 PyObject_CallFunctionObjArgs
    at ../Objects/abstract.c line 2760
  • #11 call_attribute
    at ../Objects/typeobject.c line 5441
  • #12 slot_tp_getattr_hook
    at ../Objects/typeobject.c line 5495
  • #13 PyObject_GetAttr
    at ../Objects/object.c line 1191
  • #14 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2256
  • #15 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #16 fast_function
    at ../Python/ceval.c line 4117
  • #17 call_function
    at ../Python/ceval.c line 4042
  • #18 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #19 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #20 PyEval_EvalCode
    at ../Python/ceval.c line 667
  • #21 PyImport_ExecCodeModuleEx
    at ../Python/import.c line 681
  • #22 load_source_module
    at ../Python/import.c line 1018
  • #23 load_module
    at ../Python/import.c line 1822
  • #24 import_submodule
    at ../Python/import.c line 2595
  • #25 ensure_fromlist
    at ../Python/import.c line 2506
  • #26 import_module_level
    at ../Python/import.c line 2174
  • #27 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #28 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #29 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #30 do_call
    at ../Python/ceval.c line 4236
  • #31 call_function
    at ../Python/ceval.c line 4044
  • #32 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #33 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #34 fast_function
    at ../Python/ceval.c line 4117
  • #35 call_function
    at ../Python/ceval.c line 4042
  • #36 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #37 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #38 function_call
    at ../Objects/funcobject.c line 526
  • #39 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #40 instancemethod_call
    at ../Objects/classobject.c line 2578
  • #41 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #42 call_function_tail
    at ../Objects/abstract.c line 2561
  • #43 PyObject_CallMethod
    at ../Objects/abstract.c line 2638
  • #44 load_module
    at ../Python/import.c line 1877
  • #45 import_submodule
    at ../Python/import.c line 2595
  • #46 ensure_fromlist
    at ../Python/import.c line 2506
  • #47 import_module_level
    at ../Python/import.c line 2174
  • #48 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #49 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #50 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #51 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #52 PyEval_CallObjectWithKeywords
    at ../Python/ceval.c line 3890
  • #53 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2333
  • #54 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #55 PyEval_EvalCode
    at ../Python/ceval.c line 667
  • #56 PyImport_ExecCodeModuleEx
    at ../Python/import.c line 681
  • #57 load_source_module
    at ../Python/import.c line 1018
  • #58 load_module
    at ../Python/import.c line 1822
  • #59 import_submodule
    at ../Python/import.c line 2595
  • #60 ensure_fromlist
    at ../Python/import.c line 2506
  • #61 import_module_level
    at ../Python/import.c line 2174
  • #62 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #63 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #64 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #65 do_call
    at ../Python/ceval.c line 4236
  • #66 call_function
    at ../Python/ceval.c line 4044
  • #67 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #68 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #69 fast_function
    at ../Python/ceval.c line 4117
  • #70 call_function
    at ../Python/ceval.c line 4042
  • #71 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2666
  • #72 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #73 function_call
    at ../Objects/funcobject.c line 526
  • #74 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #75 instancemethod_call
    at ../Objects/classobject.c line 2578
  • #76 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #77 call_function_tail
    at ../Objects/abstract.c line 2561
  • #78 PyObject_CallMethod
    at ../Objects/abstract.c line 2638
  • #79 load_module
    at ../Python/import.c line 1877
  • #80 import_submodule
    at ../Python/import.c line 2595
  • #81 ensure_fromlist
    at ../Python/import.c line 2506
  • #82 import_module_level
    at ../Python/import.c line 2174
  • #83 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #84 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #85 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #86 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #87 PyEval_CallObjectWithKeywords
    at ../Python/ceval.c line 3890
  • #88 PyEval_EvalFrameEx
    at ../Python/ceval.c line 2333
  • #89 PyEval_EvalCodeEx
    at ../Python/ceval.c line 3253
  • #90 PyEval_EvalCode
    at ../Python/ceval.c line 667
  • #91 PyImport_ExecCodeModuleEx
    at ../Python/import.c line 681
  • #92 load_source_module
    at ../Python/import.c line 1018
  • #93 load_module
    at ../Python/import.c line 1822
  • #94 import_submodule
    at ../Python/import.c line 2595
  • #95 load_next
    at ../Python/import.c line 2415
  • #96 import_module_level
    at ../Python/import.c line 2136
  • #97 PyImport_ImportModuleLevel
    at ../Python/import.c line 2188
  • #98 builtin___import__
    at ../Python/bltinmodule.c line 49
  • #99 PyCFunction_Call
    at ../Objects/methodobject.c line 85
  • #100 PyObject_Call
    at ../Objects/abstract.c line 2529
  • #101 call_function_tail
    at ../Objects/abstract.c line 2561
  • #102 PyObject_CallFunction
    at ../Objects/abstract.c line 2585
  • #103 PyImport_Import
    at ../Python/import.c line 2773
  • #104 call_python
    at test_embed_python.c line 35
  • #105 main
    at test_embed_python.c line 57

Comment 6 Simon Feltman 2013-04-19 22:19:34 UTC
Verified. It looks like there is lack of conformance in parts of PyGObject in regards to GC tracking. http://docs.python.org/3/c-api/gcsupport.html
Comment 7 Simon Feltman 2013-04-20 00:15:12 UTC
Created attachment 241958 [details] [review]
Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed

Remove half implemented GC tracking from PyGIBaseInfo as it was not
needed (the implemented was also missing usage of PyObject_GC_New/Track).
Ensure weakref list for PyGIBaseInfo is initialized to NULL and cleared
properly.
Remove invalid calls to PyObject_GC_UnTrack and PyObject_ClearWeakRefs
for both PyGIStruct and PyGIBoxed as these types were not being
advertised as GC aware with Py_TPFLAGS_HAVE_GC.
Comment 8 Simon Feltman 2013-04-20 00:16:53 UTC
The previous patch gets through the segfault but then runs into another problem:

Traceback (most recent call last):
  • File "/home/simon/src/gnome3/pygobject/bugs/677091/test.py", line 3 in <module>
    from gi.repository import GLib
  • File "/home/simon/opt/gnome3/lib/python2.7/site-packages/gi/importer.py", line 68 in load_module
    dynamic_module._load()
  • File "/home/simon/opt/gnome3/lib/python2.7/site-packages/gi/module.py", line 291 in _load
    overrides_modules = __import__('gi.overrides', fromlist=[self._namespace])
  • File "/home/simon/opt/gnome3/lib/python2.7/site-packages/gi/overrides/GLib.py", line 202 in <module>
    class Variant(GLib.Variant):
  • File "/home/simon/opt/gnome3/lib/python2.7/site-packages/gi/types.py", line 349 in __init__
    super(StructMeta, cls).__init__(name, bases, dict_)
TypeError: Error when calling the metaclass bases
    'NoneType' object is not callable
Comment 9 Martin Pitt 2013-05-07 03:59:19 UTC
Comment on attachment 241958 [details] [review]
Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed

TBH I'm not very familiar with how the GC works. Do you think this half-implementation would actually need to be completed to avoid memleaks here? Can you compare valgrind output before/after (note you need a python compiled with valgrind support to sensibly do that). If this doesn't cause new memleaks, this seems fine to me. Thanks!
Comment 10 Simon Feltman 2013-05-07 04:34:52 UTC
Hi Martin,

GC tracking can be used if an object holds references to other Python objects to detect reference cycles (e.g. lists and tuples). Actually I had no idea how this stuff worked either until I started researching this crash and read through:
http://docs.python.org/2/extending/newtypes.html#supporting-cyclic-garbage-collection

In the case PyGIInfo, the object doesn't hold references to other objects and the "_base_info_traverse" function is empty. There was also no usage of PyObject_GC_New, but there was usage of PyObject_GC_UnTrack, which was causing the crashes described here.

In the case of PyGIStruct and PyGIBoxed, the TP_FLAGS_HAVE_GC was not set, so the call to PyObject_GC_UnTrack was actually erroneous.

These are most likely copy/paste mistakes from the PyGObject type, which does need to support GC.
Comment 11 Martin Pitt 2013-05-07 04:41:41 UTC
Comment on attachment 241958 [details] [review]
Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed

Ah, thanks for the additional explanation!
Comment 12 Simon Feltman 2013-05-07 22:39:41 UTC
Comment on attachment 241958 [details] [review]
Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed

Attachment 241958 [details] pushed as a703217 - Remove half implemented GC in PyGIBaseInfo, PyGIStruct, and PyGIBoxed
Comment 13 Simon Feltman 2013-05-07 22:50:21 UTC
Related Python tickets:

http://bugs.python.org/issue11321
http://bugs.python.org/issue11349
http://bugs.python.org/issue812369

Related mail thread:
http://mail.python.org/pipermail/python-dev/2009-October/093029.html

It seems like PyGObject needs to be audited in regards to module cleanup and possibly implement the GC module shutdown approach described in issue812369. In general there seems to be problems with module re-loading between successive Py_Initialize and Py_Finalize calls and ref counting of Py_Types. This sounds very much like the case of the current error: "'NoneType' object is not callable" we now get with the test case.

I won't have time to revisit this for a while, so if anyone wants to take this further, have at it!
Comment 14 Simon Feltman 2014-09-13 06:52:02 UTC
Created attachment 286106 [details] [review]
tests: Setup automake parallel test harness

Additionally always link with Python libraries as this will be needed for
embedded interpreter testing.
Rename RUN_TESTS_ENV_VARS to TESTS_ENVIRONMENT which will then be used by
the parallel test harness.
Comment 15 Simon Feltman 2014-09-13 06:52:21 UTC
Created attachment 286107 [details] [review]
tests: Add test for multiple interpreter init and shutdowns

Add a simple embeded interpreter test which initializes Python, imports
pygi, calls a function, and shuts down the interpreter. This is run twice
comparing the results of GLib.get_host_name() per-run.
Comment 16 GNOME Infrastructure Team 2018-01-10 20:16:42 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/pygobject/issues/27.