TGMsgBox crashes when exiting python shell

Dear ROOTers,

I’ve found out, that if I enter a python 2.7 shell and do:

import ROOT
test_box = ROOT.TGMsgBox(ROOT.gClient.GetRoot(),0, "test", "test")

everything seems to work fine, until I exit the shell. Then I get a crash, with a final callstack being:

===========================================================
#5  0x000000e3000000e2 in ?? ()
#6  0x00007f8a58ebf66f in PyROOT::TMemoryRegulator::ClearProxiedObjects() () from /opt/root-6.20.00/lib/libPyROOT.so
#7  0x00007f8a58eb77b1 in PyROOT::ClearProxiedObjects() () from /opt/root-6.20.00/lib/libPyROOT.so
#8  0x00007f8a814821d2 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#9  0x00007f8a81482e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007f8a813ab683 in function_call () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007f8a8138eaf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007f8a8147a5e7 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007f8a81482e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#14 0x00007f8a813ab4bf in function_call () from /usr/lib64/libpython2.7.so.1.0
#15 0x00007f8a8138eaf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#16 0x00007f8a81478fc8 in PyEval_CallObjectWithKeywords () from /usr/lib64/libpython2.7.so.1.0
#17 0x00007f8a813779f8 in Py_Finalize.cold () from /usr/lib64/libpython2.7.so.1.0
#18 0x00007f8a8148860c in Py_Exit () from /usr/lib64/libpython2.7.so.1.0
#19 0x00007f8a8148853a in handle_system_exit () from /usr/lib64/libpython2.7.so.1.0
#20 0x00007f8a814882ca in PyErr_PrintEx () from /usr/lib64/libpython2.7.so.1.0
#21 0x00007f8a813778f4 in PyRun_SimpleFileExFlags.cold () from /usr/lib64/libpython2.7.so.1.0
#22 0x00007f8a8148d234 in Py_Main () from /usr/lib64/libpython2.7.so.1.0
#23 0x00007f8a811531a3 in __libc_start_main () from /usr/lib64/libc.so.6
#24 0x0000556642e250ae in _start ()
===========================================================

Am I doing something wrong in the TGMsgBox invocation?


_ROOT Version: 6.20

I think this is a PyROOT only issue (i.e. the same works fine in the ROOT command prompt) . Maybe @etejedor can help

Hi @LeWhoo,

I can’t reproduce on lxplus with ROOT 6.20:

[etejedor@lxplus767 ~]$ source /cvmfs/sft.cern.ch/lcg/views/LCG_97rc4/x86_64-centos7-gcc8-opt/setup.sh 
[etejedor@lxplus767 ~]$ root --version
ROOT Version: 6.20/00
Built for linuxx8664gcc on Feb 26 2020, 16:40:17
From tags/v6-20-00@v6-20-00
[etejedor@lxplus767 ~]$ python
Python 2.7.16 (default, Jun 13 2019, 18:33:20) 
[GCC 8.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ROOT
>>> test_box = ROOT.TGMsgBox(ROOT.gClient.GetRoot(),0, "test", "test")
TUnixSystem::SetDisplay:0: RuntimeWarning: DISPLAY not set, setting it to 2a02:1206:452a:8c00:a04a:6d86:cf0b:b65c
>>> 
[etejedor@lxplus767 ~]$ 

I also can’t reproduce in ROOT master, neither old PyROOT nor PyROOT experimental.

In what platform are you running this?

Interesting. I tried in Fedora31:

ROOT Version: 6.20/00
Built for linuxx8664gcc on Mar 03 2020, 11:39:00
From @

But also, with the same crash, on VM running Scientific Linux and ROOT 5.34.36…

I just tried one of our Fedora31 nightly builds, it is master, Python3, I can’t reproduce the issue.

I am going to build 6.20 with Python2 now to replicate your configuration. In the meantime, could you on your side try to build ROOT master on your fedora machine and check if you see the same issue?

But also, with the same crash, on VM running Scientific Linux and ROOT 5.34.36…

It might be related, but in ROOT 5 it can’t be exactly the same error, since the top of the stack trace shows a method that was added for 6.20. Anyway, let’s focus on ROOT 6 :slight_smile:

I’ve built the master:

ROOT Version: 6.21/01
Built for linuxx8664gcc on Mar 25 2020, 01:14:06
From heads/master@v6-19-01-3422-gb31d1506a0

However, I can’t simply import ROOT in python:

>>> import ROOT
Fatal in <TROOT::InitInterpreter>: cannot load library /opt/root_master/lib/libRIO.so: undefined symbol: _ZNK6TClass21HasDefaultConstructorEb

Hi,

Mmm looks like your master installation is broken. Does it happen the same if you use the build directory instead of the installation directory? You just need to go to the build directory of ROOT, and so source bin/thisroot.sh.

On my side, I tried 6.20 on fedora31, couldn’t reproduce either. How did you install 6.20 on your fedora31? Did you download the binaries? Did you build it yourself? If so, with which cmake flags?

Acutally I never install, always point ROOTSYS to the build directory. Could this be a problem?

For 6.20 I downloaded the sources and compiled myself. The only special flag was pointing to the python2.7 binary. So the whole process was:

cmake /opt/root_master_src/ -DPYTHON_EXECUTABLE=/usr/bin/python2.7
cmake --build . -- -j7

I wonder if there could be something in my settings that causes this crash. However, I renamed my rootlogon.C to avoid it being executed and the problem was still there…

OK, so if I call thisroot.sh, I can import ROOT properly from my master compilation. However, python still crashes when quitting after creating the message box. Still, I am not sure if now the experimental pyROOT is not called by default, since the stack trace points to a different library:

===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007f9a10d77eda in waitpid () from /usr/lib64/libc.so.6
#1  0x00007f9a10cf3757 in do_system () from /usr/lib64/libc.so.6
#2  0x00007f9a03590395 in TUnixSystem::StackTrace() () from /opt/root_master/lib/libCore.so
#3  0x00007f9a037c8cfa in (anonymous namespace)::TExceptionHandlerImp::HandleException(int) () from /opt/root_master/lib/python2.7/libcppyy_backend.so
#4  0x00007f9a0358d901 in TUnixSystem::DispatchSignals(ESignals) () from /opt/root_master/lib/libCore.so
#5  <signal handler called>
#6  0x000000800000007f in ?? ()
#7  0x00007f99ffa76925 in PyROOT::TMemoryRegulator::ClearProxiedObjects() () from /opt/root_master/lib/python2.7/libROOTPythonizations.so
#8  0x00007f99ffa72951 in PyROOT::ClearProxiedObjects(_object*, _object*) () from /opt/root_master/lib/python2.7/libROOTPythonizations.so
#9  0x00007f9a110001d2 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007f9a11000e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007f9a10f29683 in function_call () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007f9a10f0caf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007f9a10ff85e7 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#14 0x00007f9a11000e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#15 0x00007f9a10f294bf in function_call () from /usr/lib64/libpython2.7.so.1.0
#16 0x00007f9a10f0caf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#17 0x00007f9a10ff6fc8 in PyEval_CallObjectWithKeywords () from /usr/lib64/libpython2.7.so.1.0
#18 0x00007f9a10ef59f8 in Py_Finalize.cold () from /usr/lib64/libpython2.7.so.1.0
#19 0x00007f9a1100b025 in Py_Main () from /usr/lib64/libpython2.7.so.1.0
#20 0x00007f9a10cd11a3 in __libc_start_main () from /usr/lib64/libc.so.6
#21 0x0000557fb098b0ae in _start ()
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#6  0x000000800000007f in ?? ()
#7  0x00007f99ffa76925 in PyROOT::TMemoryRegulator::ClearProxiedObjects() () from /opt/root_master/lib/python2.7/libROOTPythonizations.so
#8  0x00007f99ffa72951 in PyROOT::ClearProxiedObjects(_object*, _object*) () from /opt/root_master/lib/python2.7/libROOTPythonizations.so
#9  0x00007f9a110001d2 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#10 0x00007f9a11000e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#11 0x00007f9a10f29683 in function_call () from /usr/lib64/libpython2.7.so.1.0
#12 0x00007f9a10f0caf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#13 0x00007f9a10ff85e7 in PyEval_EvalFrameEx () from /usr/lib64/libpython2.7.so.1.0
#14 0x00007f9a11000e18 in PyEval_EvalCodeEx () from /usr/lib64/libpython2.7.so.1.0
#15 0x00007f9a10f294bf in function_call () from /usr/lib64/libpython2.7.so.1.0
#16 0x00007f9a10f0caf7 in PyObject_Call () from /usr/lib64/libpython2.7.so.1.0
#17 0x00007f9a10ff6fc8 in PyEval_CallObjectWithKeywords () from /usr/lib64/libpython2.7.so.1.0
#18 0x00007f9a10ef59f8 in Py_Finalize.cold () from /usr/lib64/libpython2.7.so.1.0
#19 0x00007f9a1100b025 in Py_Main () from /usr/lib64/libpython2.7.so.1.0
#20 0x00007f9a10cd11a3 in __libc_start_main () from /usr/lib64/libc.so.6
#21 0x0000557fb098b0ae in _start ()
===========================================================

This new master stack trace indicates that you see the issue also with master (which has the new - experimental - PyROOT as default).

I will investigate more and report back.

From your reproducer:

import ROOT
test_box = ROOT.TGMsgBox(ROOT.gClient.GetRoot(),0, "test", "test")

I know it’s super simple already, but do you think you can simplify a bit more so that it provides us a hint of what object is triggering the failure? Is it the TGMsgBox construction, the call to GetRoot() ?

I am not sure how I could simplify this. Instead of GetRoot() I could create another window and make it parent, but this window would have to use GetRoot() instead…

Does this also crash?

test_box = ROOT.TGMsgBox(ROOT.nullptr,0, "test", "test")

No, this is stable. However, does not show any message box - I guess as expected.

What about:

import ROOT
x = ROOT.gClient.GetRoot()

This does not crash in the master. Interestingly, it does not work in 6.20:

>>> a = ROOT.gClient.GetRoot()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/root-6.20.00/lib/ROOT.py", line 629, in __getattr1
    return getattr( self, name )
  File "/opt/root-6.20.00/lib/ROOT.py", line 674, in __getattr2
    raise AttributeError( name )
AttributeError: gClient

but perhaps it is irrelevant.

Mmm ok so it seems that, for PyROOT to find gClient, it needs to first look up TGMsgBox. I see the same behaviour with master, and this fixes it:

import ROOT
ROOT.TGMsgBox
x = ROOT.gClient.GetRoot()

I will investigate this a bit (this one I can reprocuce) and see if can be related to the first issue you reported.

Also in the meantime, could you run, in master:

import ROOT
from ROOT import SetOwnership
test_box = ROOT.TGMsgBox(ROOT.gClient.GetRoot(),0, "test", "test")
SetOwnership(test_box, False)

and tell me if that crashes with the initial stack trace?

Great. This is stable both in master and in 6.20 :slight_smile:

Ok, this indicates that the poor TGMsgBox guy is being double deleted, once by PyROOT and again by C++. Once we tell PyROOT not to delete it, the issue disappears. Now, why C++ is also deleting it under the hood, I need to find out.

But at least that can help you get going without the crash for now.