ROOT.gApplication.Run() and threading

Dear PyROOTers,

I recently switched from waiting for the keyboard input to ROOT.gApplication.Run(). However, it seems to break multithreading.

I know that in general PyROOT is not thread safe, but feeling some windows from trees, etc. worked very well in separate threads when I was a while() loop with raw_input. They do not work when I switched to ROOT.gApplication.Run(). Even simple printing a message than waiting for 1 second in the loop does not seem to work properly in this case - the message is displayed sometimes, I think in some cases when the main window gets updated (although not sure about it).

Is there any way to have multithreading while using ROOT.gApplication.Run()?

Hi,

I think that’s basically impossible to answer given the information you provided :frowning:

Can you give us well-formed code that reproduces what you want to achieve and at the same time shows what doesn’t work?

Cheers, Axel.

Here you are. Unfortunately I did not find a way to force it to print the text from inside the thread - sometimes when I run it it prints “in thread” once. Most of the time it doesn’t. If one comments out ROOT.gApplication.Run() and uncomments the part with raw_input it works flawlessly.
thread_test.py (691 Bytes)

Hi,

I have asked Wim and Philippe for help since I won’t have time during the next days…

Axel.

Hi,

[quote=“Axel”]I have asked Wim and Philippe for help since I won’t have time during the next days…[/quote]and I’ve got my ‘CS’ hat on for at least the coming week or two …

But this should do:ROOT.gApplication.Run._threaded = True ROOT.gApplication.Run()
And yes, there are holes in the PyROOT hand-off of the GIL (although you’d be hard-pressed to hit them). But that’s why I’ve done a complete refactoring of most of PyROOT to close such holes (this for GaudiHive). That’s only in ROOT6 master, though, and only since a few days.

Cheers,
Wim

No way to somehow manually work-around it in ROOT 5?

Hi,[quote=“LeWhoo”]No way to somehow manually work-around it in ROOT 5?[/quote]the “_threaded = True” works in both ROOT5 and ROOT6, just that the old implementation has some holes, but they are hard to hit (if you were to have exceptions at the same time in two threads, for example, that could be bad).

Cheers,
Wim

It seems I’m unlucky. I added the _threaded and app crashes at the very beginning with different errors:

Short example:

Error in <RootX11ErrorHandler>: BadPixmap (invalid Pixmap parameter) (XID: 71303400, XREQ: 54)
Error in <RootX11ErrorHandler>: BadIDChoice (invalid resource ID chosen for this connection) (XID: 71303525, XREQ: 53)
^\Quit (core dumped)

long example:

Error in <RootX11IOErrorHandler>: Canvas width changed from 0 to 10


**** Save data and exit application ****


 *** Break *** segmentation violation
TCanvas::ResizePad:0: RuntimeWarning: Canvas width changed from 0 to 10

TCanvas::ResizePad:0: RuntimeWarning: Canvas height changed from 0 to 10

Xlib: request 70 length 20 would exceed buffer size.

 *** Break *** segmentation violation
Xlib: request 4 length 8 would exceed buffer size.



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================

Thread 2 (Thread 0x7f1ff1ff1700 (LWP 4548)):
#0  0x000000395c8c456b in waitpid () from /lib64/libc.so.6
#1  0x000000395c842a2b in do_system () from /lib64/libc.so.6
#2  0x00007f1ffb4d9409 in TUnixSystem::StackTrace() () from /opt/root/lib/libCore.so
#3  0x00007f1ffb4db01c in TUnixSystem::DispatchSignals(ESignals) () from /opt/root/lib/libCore.so
#4  <signal handler called>
#5  0x00000039834eb5c1 in PyErr_Restore () from /lib64/libpython2.7.so.1.0
#6  0x00000039834eb6af in PyErr_SetString () from /lib64/libpython2.7.so.1.0
#7  0x00007f1ffe1d485e in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe(void*, bool) () from /opt/root/lib/libPyROOT.so
#8  0x00007f1ffe1d4952 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute(void*, bool) () from /opt/root/lib/libPyROOT.so
#9  0x00007f1ffe1d38ad in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /opt/root/lib/libPyROOT.so
#10 0x00007f1ffe1c996d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /opt/root/lib/libPyROOT.so
#11 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#12 0x00000039834e0585 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#13 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#14 0x000000398346f6bd in function_call () from /lib64/libpython2.7.so.1.0
#15 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#16 0x00000039834e0050 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#17 0x00000039834e1be6 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#18 0x00000039834e1be6 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#19 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#20 0x000000398346f5dc in function_call () from /lib64/libpython2.7.so.1.0
#21 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#22 0x0000003983459815 in instancemethod_call () from /lib64/libpython2.7.so.1.0
#23 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#24 0x00000039834dc4c7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#25 0x0000003983512062 in t_bootstrap () from /lib64/libpython2.7.so.1.0
#26 0x000000395cc0752a in start_thread () from /lib64/libpthread.so.0
#27 0x000000395c90079d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f2005db7700 (LWP 4541)):
#0  0x000000395c8c456b in waitpid () from /lib64/libc.so.6
#1  0x000000395c842a2b in do_system () from /lib64/libc.so.6
#2  0x00007f1ffb4d9409 in TUnixSystem::StackTrace() () from /opt/root/lib/libCore.so
#3  0x00007f1ffb4db01c in TUnixSystem::DispatchSignals(ESignals) () from /opt/root/lib/libCore.so
#4  <signal handler called>
#5  0x00000038e0224287 in XFillRectangle () from /lib64/libX11.so.6
#6  0x00007f1ff34a1212 in TGX11::DrawBox(int, int, int, int, TVirtualX::EBoxMode) () from /opt/root/lib/libGX11.so
#7  0x00007f1ffc8c79b1 in TPad::PaintBox(double, double, double, double, char const*) () from /opt/root/lib/libGpad.so
#8  0x00007f1febab8e36 in THistPainter::PaintColorLevels(char const*) () from /opt/root/lib/libHistPainter.so
#9  0x00007f1feba9d1e6 in THistPainter::PaintTable(char const*) () from /opt/root/lib/libHistPainter.so
#10 0x00007f1feba9f8fc in THistPainter::Paint(char const*) () from /opt/root/lib/libHistPainter.so
#11 0x00007f1ffc8ceb49 in TPad::PaintModified() () from /opt/root/lib/libGpad.so
#12 0x00007f1ffc8b291c in TCanvas::Update() () from /opt/root/lib/libGpad.so
#13 0x00007f1ff30e2439 in TRootEmbeddedCanvas::HandleContainerConfigure(Event_t*) () from /opt/root/lib/libGui.so
#14 0x00007f1ff309a933 in TGFrame::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#15 0x00007f1ff31005b8 in TGClient::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#16 0x00007f1ff310086d in TGClient::ProcessOneEvent() () from /opt/root/lib/libGui.so
#17 0x00007f1ff31008cd in TGClient::HandleInput() () from /opt/root/lib/libGui.so
#18 0x00007f1ffb4db288 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/lib/libCore.so
#19 0x00007f1ffb513456 in TSystem::InnerLoop() () from /opt/root/lib/libCore.so
#20 0x00007f1ffb514000 in TSystem::Run() () from /opt/root/lib/libCore.so
#21 0x00007f1ffb533d1f in TApplication::Run(bool) () from /opt/root/lib/libCore.so
#22 0x00007f1ffb35e3d3 in G__G__Base1_305_0_23(G__value*, char const*, G__param*, int) () from /opt/root/lib/libCore.so
#23 0x00007f1ffa86c11b in Cint::G__CallFunc::Execute(void*) () from /opt/root/lib/libCint.so
#24 0x00007f1ffe1c019e in PyROOT::TVoidExecutor::Execute(Cint::G__CallFunc*, void*, bool) () from /opt/root/lib/libPyROOT.so
#25 0x00007f1ffe1d47e0 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe(void*, bool) () from /opt/root/lib/libPyROOT.so
#26 0x00007f1ffe1d4952 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute(void*, bool) () from /opt/root/lib/libPyROOT.so
#27 0x00007f1ffe1d38ad in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /opt/root/lib/libPyROOT.so
#28 0x00007f1ffe1c996d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /opt/root/lib/libPyROOT.so
#29 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#30 0x00000039834e0585 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#31 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#32 0x00000039834e34f9 in PyEval_EvalCode () from /lib64/libpython2.7.so.1.0
#33 0x00000039834fc90f in run_mod () from /lib64/libpython2.7.so.1.0
#34 0x00000039834fdb32 in PyRun_FileExFlags () from /lib64/libpython2.7.so.1.0
#35 0x00000039834fed47 in PyRun_SimpleFileExFlags () from /lib64/libpython2.7.so.1.0
#36 0x00000039835102ea in Py_Main () from /lib64/libpython2.7.so.1.0
#37 0x000000395c81ffe0 in __libc_start_main () from /lib64/libc.so.6
#38 0x000000000040071e in _start ()
===========================================================

or

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================

Thread 2 (Thread 0x7f5fec069700 (LWP 4859)):
#0  0x000000395c8f51fd in poll () from /lib64/libc.so.6
#1  0x00000038e060a182 in _xcb_conn_wait () from /lib64/libxcb.so.1
#2  0x00000038e060bcff in xcb_wait_for_event () from /lib64/libxcb.so.1
#3  0x00000038e0243068 in _XReadEvents () from /lib64/libX11.so.6
#4  0x00000038e0232148 in XNextEvent () from /lib64/libX11.so.6
#5  0x00007f5fed5232bf in TGX11::NextEvent(Event_t&) () from /opt/root/lib/libGX11.so
#6  0x00007f5fed17882c in TGClient::ProcessOneEvent() () from /opt/root/lib/libGui.so
#7  0x00007f5fed1788cd in TGClient::HandleInput() () from /opt/root/lib/libGui.so
#8  0x00007f5ff5553288 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/lib/libCore.so
#9  0x00007f5ff558b48e in TSystem::ProcessEvents() () from /opt/root/lib/libCore.so
#10 0x00007f5ff52b8ed5 in G__G__Base2_325_0_25(G__value*, char const*, G__param*, int) () from /opt/root/lib/libCore.so
#11 0x00007f5ff48e411b in Cint::G__CallFunc::Execute(void*) () from /opt/root/lib/libCint.so
#12 0x00007f5ff82388fe in PyROOT::TBoolExecutor::Execute(Cint::G__CallFunc*, void*, bool) () from /opt/root/lib/libPyROOT.so
#13 0x00007f5ff824c7e0 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe(void*, bool) () from /opt/root/lib/libPyROOT.so
#14 0x00007f5ff824c952 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute(void*, bool) () from /opt/root/lib/libPyROOT.so
#15 0x00007f5ff824b8ad in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /opt/root/lib/libPyROOT.so
#16 0x00007f5ff824196d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /opt/root/lib/libPyROOT.so
#17 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#18 0x00000039834e0585 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#19 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#20 0x000000398346f6bd in function_call () from /lib64/libpython2.7.so.1.0
#21 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#22 0x00000039834e0050 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#23 0x00000039834e1be6 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#24 0x00000039834e1be6 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#25 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#26 0x000000398346f5dc in function_call () from /lib64/libpython2.7.so.1.0
#27 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#28 0x0000003983459815 in instancemethod_call () from /lib64/libpython2.7.so.1.0
#29 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#30 0x00000039834dc4c7 in PyEval_CallObjectWithKeywords () from /lib64/libpython2.7.so.1.0
#31 0x0000003983512062 in t_bootstrap () from /lib64/libpython2.7.so.1.0
#32 0x000000395cc0752a in start_thread () from /lib64/libpthread.so.0
#33 0x000000395c90079d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f5fffe2f700 (LWP 4852)):
#0  0x000000395c8c456b in waitpid () from /lib64/libc.so.6
#1  0x000000395c842a2b in do_system () from /lib64/libc.so.6
#2  0x00007f5ff5551409 in TUnixSystem::StackTrace() () from /opt/root/lib/libCore.so
#3  0x00007f5ff555301c in TUnixSystem::DispatchSignals(ESignals) () from /opt/root/lib/libCore.so
#4  <signal handler called>
#5  0x00007f5ff54ff53c in TList::Remove(TObject*) () from /opt/root/lib/libCore.so
#6  0x00007f5ff550223e in THashList::Remove(TObject*) () from /opt/root/lib/libCore.so
#7  0x00007f5ff555c6b3 in TObjectSpy::~TObjectSpy() () from /opt/root/lib/libCore.so
#8  0x00007f5fed1128c8 in TGFrame::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#9  0x00007f5fed1785b8 in TGClient::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#10 0x00007f5fed17886d in TGClient::ProcessOneEvent() () from /opt/root/lib/libGui.so
#11 0x00007f5fed1788cd in TGClient::HandleInput() () from /opt/root/lib/libGui.so
#12 0x00007f5ff5553288 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/lib/libCore.so
#13 0x00007f5ff558b456 in TSystem::InnerLoop() () from /opt/root/lib/libCore.so
#14 0x00007f5ff558c000 in TSystem::Run() () from /opt/root/lib/libCore.so
#15 0x00007f5ff55abd1f in TApplication::Run(bool) () from /opt/root/lib/libCore.so
#16 0x00007f5ff53d63d3 in G__G__Base1_305_0_23(G__value*, char const*, G__param*, int) () from /opt/root/lib/libCore.so
#17 0x00007f5ff48e411b in Cint::G__CallFunc::Execute(void*) () from /opt/root/lib/libCint.so
#18 0x00007f5ff823819e in PyROOT::TVoidExecutor::Execute(Cint::G__CallFunc*, void*, bool) () from /opt/root/lib/libPyROOT.so
#19 0x00007f5ff824c7e0 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe(void*, bool) () from /opt/root/lib/libPyROOT.so
#20 0x00007f5ff824c952 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute(void*, bool) () from /opt/root/lib/libPyROOT.so
#21 0x00007f5ff824b8ad in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /opt/root/lib/libPyROOT.so
#22 0x00007f5ff824196d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /opt/root/lib/libPyROOT.so
#23 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#24 0x00000039834e0585 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
#25 0x00000039834e3400 in PyEval_EvalCodeEx () from /lib64/libpython2.7.so.1.0
#26 0x00000039834e34f9 in PyEval_EvalCode () from /lib64/libpython2.7.so.1.0
#27 0x00000039834fc90f in run_mod () from /lib64/libpython2.7.so.1.0
#28 0x00000039834fdb32 in PyRun_FileExFlags () from /lib64/libpython2.7.so.1.0
#29 0x00000039834fed47 in PyRun_SimpleFileExFlags () from /lib64/libpython2.7.so.1.0
#30 0x00000039835102ea in Py_Main () from /lib64/libpython2.7.so.1.0
#31 0x000000395c81ffe0 in __libc_start_main () from /lib64/libc.so.6
#32 0x000000000040071e in _start ()
===========================================================

I’m on ROOT 5.34/15.

I guess now you would like me to provide an example code. This may take a while…

Hi,

those are problems from threading in ROOT, not in PyROOT, so it would make no difference before/after the factorization. Yes, I’m in uncharted waters here, so a reproducer would be nice, but both call “TUnixSystem::DispatchOneEvent(bool)” (per the stack trace), and the raison d’etre of the second (GUI) thread is purely to call just that. So, if you add, right after “import ROOT” (wherever it is first imported):import ROOT ROOT.PyConfig.StartGuiThread = Falsethen the Run() call should keep the GUI from starving, and you won’t see this crash.

Could you try?

Cheers,
Wim

Unfortunately, still crashing:

===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x000000395c8c451a in waitpid () from /lib64/libc.so.6
#1  0x000000395c842a2b in do_system () from /lib64/libc.so.6
#2  0x00007ff742936409 in TUnixSystem::StackTrace() () from /opt/root/lib/libCore.so
#3  0x00007ff74293801c in TUnixSystem::DispatchSignals(ESignals) () from /opt/root/lib/libCore.so
#4  <signal handler called>
#5  0x00000039834f278b in PyImport_GetModuleDict () from /lib64/libpython2.7.so.1.0
#6  0x00000039834f2edc in PyImport_AddModule () from /lib64/libpython2.7.so.1.0
#7  0x00007ff745607fa4 in TPython::Initialize() () from /opt/root/lib/libPyROOT.so
#8  0x00007ff7456082f0 in TPython::Exec(char const*) () from /opt/root/lib/libPyROOT.so
#9  0x00007ff7455f9bdc in G__G__PyROOT_114_0_4(G__value*, char const*, G__param*, int) () from /opt/root/lib/libPyROOT.so
#10 0x00007ff741bc8b9d in Cint::G__ExceptionWrapper(int (*)(G__value*, char const*, G__param*, int), G__value*, char*, G__param*, int) () from /opt/root/lib/libCint.so
#11 0x00007ff741b2f807 in G__execute_call () from /opt/root/lib/libCint.so
#12 0x00007ff741b2fbc5 in G__call_cppfunc () from /opt/root/lib/libCint.so
#13 0x00007ff741ba32e0 in G__interpret_func () from /opt/root/lib/libCint.so
#14 0x00007ff741bf47e7 in G__getfunction () from /opt/root/lib/libCint.so
#15 0x00007ff741b58e52 in G__getitem () from /opt/root/lib/libCint.so
#16 0x00007ff741b5e2e5 in G__getexpr () from /opt/root/lib/libCint.so
#17 0x00007ff741bde765 in G__exec_statement () from /opt/root/lib/libCint.so
#18 0x00007ff741b6e946 in G__exec_tempfile_core () from /opt/root/lib/libCint.so
#19 0x00007ff741b6fe2e in G__exec_tempfile_fp () from /opt/root/lib/libCint.so
#20 0x00007ff741bfc2b9 in G__process_cmd () from /opt/root/lib/libCint.so
#21 0x00007ff742907a0f in TCint::ProcessLine(char const*, TInterpreter::EErrorCode*) () from /opt/root/lib/libCore.so
#22 0x00007ff7429921d2 in TApplication::ProcessLine(char const*, bool, int*) () from /opt/root/lib/libCore.so
#23 0x00007ff74294ff4c in TROOT::ProcessLine(char const*, int*) () from /opt/root/lib/libCore.so
#24 0x00007ff7429488d7 in TExec::Exec(char const*) [clone .part.1] () from /opt/root/lib/libCore.so
#25 0x00007ff743d252e3 in TPad::AutoExec() () from /opt/root/lib/libGpad.so
#26 0x00007ff743d0fb11 in TCanvas::EnterLeave(TPad*, TObject*) () from /opt/root/lib/libGpad.so
#27 0x00007ff743d0ff60 in TCanvas::HandleInput(EEventType, int, int) () from /opt/root/lib/libGpad.so
#28 0x00007ff73a531fe4 in TRootEmbeddedCanvas::HandleContainerMotion(Event_t*) () from /opt/root/lib/libGui.so
#29 0x00007ff73a4ea8a1 in TGFrame::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#30 0x00007ff73a5505b8 in TGClient::HandleEvent(Event_t*) () from /opt/root/lib/libGui.so
#31 0x00007ff73a55086d in TGClient::ProcessOneEvent() () from /opt/root/lib/libGui.so
#32 0x00007ff73a5508cd in TGClient::HandleInput() () from /opt/root/lib/libGui.so
#33 0x00007ff742938288 in TUnixSystem::DispatchOneEvent(bool) () from /opt/root/lib/libCore.so
#34 0x00007ff742970456 in TSystem::InnerLoop() () from /opt/root/lib/libCore.so
#35 0x00007ff742971000 in TSystem::Run() () from /opt/root/lib/libCore.so
#36 0x00007ff742990d1f in TApplication::Run(bool) () from /opt/root/lib/libCore.so
#37 0x00007ff7427bb3d3 in G__G__Base1_305_0_23(G__value*, char const*, G__param*, int) () from /opt/root/lib/libCore.so
#38 0x00007ff741cc911b in Cint::G__CallFunc::Execute(void*) () from /opt/root/lib/libCint.so
#39 0x00007ff74561d19e in PyROOT::TVoidExecutor::Execute(Cint::G__CallFunc*, void*, bool) () from /opt/root/lib/libPyROOT.so
#40 0x00007ff7456317e0 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::CallSafe(void*, bool) () from /opt/root/lib/libPyROOT.so
#41 0x00007ff745631952 in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::Execute(void*, bool) () from /opt/root/lib/libPyROOT.so
#42 0x00007ff7456308ad in PyROOT::TMethodHolder<PyROOT::TScopeAdapter, PyROOT::TMemberAdapter>::operator()(PyROOT::ObjectProxy*, _object*, _object*, long, bool) () from /opt/root/lib/libPyROOT.so
#43 0x00007ff74562696d in PyROOT::(anonymous namespace)::mp_call(PyROOT::MethodProxy*, _object*, _object*) () from /opt/root/lib/libPyROOT.so
#44 0x000000398344a903 in PyObject_Call () from /lib64/libpython2.7.so.1.0
#45 0x00000039834e0585 in PyEval_EvalFrameEx () from /lib64/libpython2.7.so.1.0
and so on...

Hi,

that one I do understand and is the motivation for the refactoring. It’s the problem as seen in GaudiHIve: after releasing the GIL, when the C++ code calls back into Python again (after having started from a python call that release the GIL), the GIL needs to be re-acquired. That has to be done on the C++ side (in TPython::Exec).

Okay, another option then. Instead of gApplication.Run(), use:while 1: try: ROOT.gSystem.ProcessEvents() time.sleep( 0.01 ) except Exception: # in case gSystem gets destroyed early on exit passAnd make sure that the GUI thread is still switched off as before.

What this does, is the work of the GUI thread (from which the above code is lifted), but now on the main thread. The “while 1” will prevent exit until the interpreter exits. Since it is in python, it will play nice with other python threads.

Cheers,
Wim

Works!

However, I am not sure how to close the app. I do now

		ROOT.gApplication.Terminate(0)
		ROOT.gSystem.Exit(0)

and seems to work. When using gApplication.Run() only the terminate was needed, which didnt work however with the raw_input() loop.

Hi,

that is simple to understand. Terminate() looks like:[code]void TApplication::Terminate(Int_t status)
{
// Terminate the application by call TSystem::Exit() unless application has
// been told to return from Run(), by a call to SetReturnFromRun().

Emit(“Terminate(Int_t)”, status);

if (fReturnFromRun)
gSystem->ExitLoop();
else {
//close TMemStat
if (fUseMemstat) {
ProcessLine(“TMemStat::Close()”);
fUseMemstat = kFALSE;
}

  gSystem->Exit(status);

}
}[/code]
and fReturnFromRun will be true (as TPyROOTApplication sets it to kTRUE). But if you called gApplication.Run(), then it takes a parameter that sets fReturnFromRun and the default choice is false.

Cheers,
Wim

[quote=“wlav”]Hi,
Okay, another option then. Instead of gApplication.Run(), use:while 1: try: ROOT.gSystem.ProcessEvents() time.sleep( 0.01 ) except Exception: # in case gSystem gets destroyed early on exit passAnd make sure that the GUI thread is still switched off as before.

[/quote]

I did not spot it instantly, but this code causes a 100% cpu hog on my machine…

Hi,

yes; standard problem with polling. You can increase the sleep time.

Cheers,
Wim

That was the first thing I tried and seemed to have no impact… Anyway, already 0.01 sleep time should be very long for an average computer.

Hi,

One thing that might be missing from the original code is to enable thread support (proper protection of shared data, like TClasses) in ROOT by calling:TThread::Initialize();and creating on TThread per thread.

Cheers,
Philippe.

You mean using TThreads instead of Python threads?

Hi,

You can use TThread instead of python thread but what I meant is that even if you use python thread the code run inside the python thread must create a TThread to enable the legacy (this will be address in future release of v6) thread local storage mechanism.

Cheers,
Philippe.

OK, I understand more, but it is still not obvious to me. So in each python thread I create I should create a TThread object and call its initialize. So something like:

def my_thread1_function():
 rt = ROOT.Thread()
 rt.Initialize()

 further_thread_code...

inside a function called by each thread is enough?