Stack trace from exception in RDF loop called from python?

Hello,

I’m running RDataframe from python, and some C++ called within the event loop throws a C++ exception. Currently, what I get is a python stack trace and the c++ exception name and what() string, e.g.

RDataFrame::Run: event loop was interrupted
Traceback (most recent call last):
  File "/eos/home-g/gpetrucc/SWAN_projects/CMGRDF-test/cmgrdf-prototype/examples/run_SFs_ttHH_2018c.py", line 158, in <module>
    result_plots = maker.runPlots()
  File "/eos/home-g/gpetrucc/SWAN_projects/CMGRDF-test/cmgrdf-prototype/python/CMGRDF/processor.py", line 302, in runPlots
    rawReport = self._runAllRaw(logPerformance=logPerformance, **kwargs)
  File "/eos/home-g/gpetrucc/SWAN_projects/CMGRDF-test/cmgrdf-prototype/python/CMGRDF/processor.py", line 275, in _runAllRaw
    ROOT.RDF.RunGraphs([fut[-2] for fut in self._futures])
cppyy.gbl.std.runtime_error: void ROOT::RDF::RunGraphs(vector<ROOT::RDF::RResultHandle>) =>
    runtime_error: Too many inputs

However, from this it’s hard to tell the C++ source of the exception.

Is there a way to get the stack trace of the C++ exception or have root print it?

I can get it by running python3 within gdb and doing catch throw and skipping over the other python exceptions that don’t cause the event loop to stop, but that’s a bit tricky as recipe to give to an end user.

Thanks

ROOT Version: ROOT 6.28/06
Platform: amd64
Compiler: g++ (GCC) 11.3.0


Hi Giovanni,

Thanks for the post and welcome to the ROOT Community!
Let me start by adding @mczurylo @vpadulan @silverweed in the loop.
I agree this is less than optimal, and the error should be more telling. Can we have a reproducer for his problem?

Cheers,
D

Reproducer code
I need to create an actual C++ library because if I just define all the functions in gIntepreter.Declare the stack traces don’t appear even in gdb

import os
ccfile = open("reproducer.cc", "w")
ccfile.write('''
#include <stdexcept>

float funcA(float a, float b) {
    if (a > b) throw std::runtime_error("Informative error message");
    return b - a;
}

float funcB(float a, float b, float c) {
    return funcA(a, b) + c;
}

float funcC(float a, float b, float c) {
    return a + b + funcB(a, b, c);
}
''')
ccfile.close()
os.system("g++ $(root-config --cflags) -fPIC -ggdb -c reproducer.cc")
os.system("g++ $(root-config --ldflags) -shared -Wl,-soname,reproducer -Wl,-E -Wl,-z,defs -fPIC reproducer.o -o libreproducer.so")

import ROOT
ROOT.gSystem.Load("libreproducer.so")
ROOT.gInterpreter.Declare("float funcC(float a, float b, float c) ;")
d = ROOT.RDataFrame(10)
d = d.Define("a", "float(0.3*rdfentry_)")
d = d.Define("b", "2")
d = d.Define("c", "float(3*rdfentry_)")
d = d.Define("f", "funcC(a,b,c)")
d = d.Filter("f > 0")
npass = d.Count().GetValue()

print(npass)

Output

RDataFrame::Run: event loop was interrupted
Traceback (most recent call last):
  File "reproducer.py", line 32, in <module>
    npass = d.Count().GetValue()
cppyy.gbl.std.runtime_error: const ULong64_t& ROOT::RDF::RResultPtr<ULong64_t>::GetValue() =>
    runtime_error: Informative error message

Stack trace with GDB

(gdb) catch throw
Catchpoint 1 (throw)
(gdb) r reproducer.py
Starting program: /usr/bin/python3 reproducer.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[Detaching after vfork from child process 643799]
[Detaching after vfork from child process 643812]
[Detaching after vfork from child process 643825]
[Detaching after vfork from child process 643827]
[Detaching after vfork from child process 643831]
[Detaching after vfork from child process 643833]

Catchpoint 1 (exception thrown), 0x00007ffff52887d1 in __cxa_throw () from /lib64/libstdc++.so.6
(gdb) bt
#0  0x00007ffff52887d1 in __cxa_throw () from /lib64/libstdc++.so.6
#1  0x00007fffdfdef9c1 in funcA (a=2.0999999, b=2) at reproducer.cc:5
#2  0x00007fffdfdefa12 in funcB (a=2.0999999, b=2, c=21) at reproducer.cc:10
#3  0x00007fffdfdefa53 in funcC (a=2.0999999, b=2, c=21) at reproducer.cc:14
#4  0x00007fffe250802c in ?? ()
#5  0x000055555b74bd70 in ?? ()
#6  0x40066666da452d9e in ?? ()
#7  0x00007fffffffc880 in ?? ()

Dear @gpetruc ,

There is no feature better than stepping through gdb at the moment. But we can definitely think of something to improve the user experience, this could be injected in RDataFrame or maybe there’s a chance to instruct cppyy to print also the C++ stacktrace. I will keep you posted.

As a side note

I need to create an actual C++ library because if I just define all the functions in gIntepreter.Declare the stack traces don’t appear even in gdb

You should be able to see the C++ stack traces from jitted code by setting the environment variable CLING_DEBUG=1 before starting the gdb session.

Cheers,
Vincenzo

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.