Multithreading & TFiles

Hello,

I’m trying to load a root file on one thread and use the loaded data in another. The code however will segfault in the TObject::Clone functions. It will however work if I fully load and close the file before trying to copy the data onto the other thread (somewhat negating the point).
I’ve read older articles that state that ROOT is not thread safe, is it still the case that TFiles, TTrees etc… are not thread safe?

Thanks
Phil

Hi Phil,

The current status is that if only one thread can access one TFile object, the access to the TFile/TTree are safe as long as all meta data (TClass/TStreamerInfo) have been setup serially (i.e. in first approximation the first access to any object type needs to happen serially … yes this is a significant constraint that we can only lift in the cling era).

[quote]The code however will segfault in the TObject::Clone functions.[/quote]TObject::Clone had an unfortunately deficiency introduced in v5.32 when using Thread which has been fixed in the trunk and in the v5.32 patch branch (including in v5.32/01).

Cheers,
Philippe.

ROOT 5.32.01 doesn’t seem to fix my problem as I still get a segfault in TDirectory::CloneObject. Is this expected with this ROOT version?

Hi,

No it is not expected. Could you provide a complete running example reproducing the problem?

Thanks,
Philippe.

Sorry for the long delay in responding.

It’s fairly difficult to simplify the code sufficiently to post here, so I’d like to try the following first.

I’ve now reverted to root 5.28 and this error is no longer present, I’ll try root 5.30 next. Do you know any relevant changes that may have caused this between 5.28 and 5.32?

Thanks
Phil

The error is also not present in 5.30.06.

Hi,

There have been many change between v5.28 and 5.30/06 and it would be almost impossible to tell which one caused the problem … (in addition, since this is a thread issue, the problem might be present in v5.28 but manifest itself in a tamer way).

What is the stack trace at the time of the crash? Does the problem goes away (i.e. no warnings) when running with valgrind?

Philippe.

Stack trace:

#0  0x00007f89f3b02fbd in waitpid () from /lib/libc.so.6
#1  0x00007f89f3a9a7e9 in ?? () from /lib/libc.so.6
#2  0x00007f89f3a9ab20 in system () from /lib/libc.so.6
#3  0x00007f89f922e0d4 in TUnixSystem::StackTrace() () from /home//snocave/libraries/root-5.32.00/lib/libCore.so
#4  0x00007f89f922cb03 in TUnixSystem::DispatchSignals(ESignals) () from /home//snocave/libraries/root-5.32.00/lib/libCore.so
#5  <signal handler called>
#6  0x00007f89f82d08ff in TGenCollectionStreamer::Streamer(TBuffer&) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#7  0x00007f89f829cb26 in TCollectionStreamer::Streamer(TBuffer&, void*, int, TClass*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#8  0x00007f89f829af59 in TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#9  0x00007f89f8369809 in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#10 0x00007f89f82e10fe in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#11 0x00007f89f8295b65 in TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#12 0x00007f89f8295c05 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#13 0x00007f89f829bd1e in TBufferFile::WriteObjectClass(void const*, TClass const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#14 0x00007f89f829905f in TBufferFile::WriteObjectAny(void const*, TClass const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#15 0x00007f89f82cf13d in TGenCollectionStreamer::WriteObjects(int, TBuffer&) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#16 0x00007f89f82d096e in TGenCollectionStreamer::Streamer(TBuffer&) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#17 0x00007f89f829cb26 in TCollectionStreamer::Streamer(TBuffer&, void*, int, TClass*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#18 0x00007f89f829af59 in TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#19 0x00007f89f8369809 in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#20 0x00007f89f82e10fe in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#21 0x00007f89f8295b65 in TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#22 0x00007f89f8295c05 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#23 0x00007f89f829f942 in TDirectoryFile::CloneObject(TObject const*, bool) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#24 0x00000000004c87cf in RAT::DS::Root::CopyObj (this=0x4672410, rhs=...) at /home//snocave/rat/include/RAT/DS/Root.hh:183
#25 0x00000000004c85d5 in Root (this=0x4672410, rhs=...) at /home//snocave/rat/include/RAT/DS/Root.hh:68
#26 0x00000000004c7570 in Viewer::EventData::Initialise (this=0x9bce40) at src/Data/EventData.cc:20
#27 0x00000000004d2a94 in Initialise () at SNOGoggles.cc:101
#28 0x00000000004d2a03 in main (argc=2, argv=0x7fffa6ebaa28) at SNOGoggles.cc:86

Other Thread:
#0  0x00007f89f3b02fbd in waitpid () from /lib/libc.so.6
#1  0x00007f89f3a9a7e9 in ?? () from /lib/libc.so.6
#2  0x00007f89f3a9ab20 in system () from /lib/libc.so.6
#3  0x00007f89f922e0d4 in TUnixSystem::StackTrace() () from /home//snocave/libraries/root-5.32.00/lib/libCore.so
#4  0x00007f89f922cb03 in TUnixSystem::DispatchSignals(ESignals) () from /home//snocave/libraries/root-5.32.00/lib/libCore.so
#5  <signal handler called>
#6  0x00007f89f82caab8 in TGenCollectionProxy::PushProxy(void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#7  0x00007f89f829cb06 in TCollectionStreamer::Streamer(TBuffer&, void*, int, TClass*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#8  0x00007f89f829af59 in TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#9  0x00007f89f8369809 in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#10 0x00007f89f82e10fe in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#11 0x00007f89f8295b65 in TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#12 0x00007f89f8295c05 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#13 0x00007f89f829bd1e in TBufferFile::WriteObjectClass(void const*, TClass const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#14 0x00007f89f829905f in TBufferFile::WriteObjectAny(void const*, TClass const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#15 0x00007f89f82cf13d in TGenCollectionStreamer::WriteObjects(int, TBuffer&) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#16 0x00007f89f82d096e in TGenCollectionStreamer::Streamer(TBuffer&) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#17 0x00007f89f829cb26 in TCollectionStreamer::Streamer(TBuffer&, void*, int, TClass*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#18 0x00007f89f829af59 in TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#19 0x00007f89f8369809 in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, int, int, int, int) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#20 0x00007f89f82e10fe in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#21 0x00007f89f8295b65 in TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#22 0x00007f89f8295c05 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#23 0x00007f89f829f942 in TDirectoryFile::CloneObject(TObject const*, bool) () from /home//snocave/libraries/root-5.32.00/lib/libRIO.so
#24 0x00000000004c87cf in RAT::DS::Root::CopyObj (this=0x453b560, rhs=...) at /home//snocave/rat/include/RAT/DS/Root.hh:183
#25 0x00000000004c85d5 in Root (this=0x453b560, rhs=...) at /home//snocave/rat/include/RAT/DS/Root.hh:68
#26 0x00000000004c7aaa in Viewer::EventData::AddDS (this=0x9bce40, rDS=0x3a0a9e0) at src/Data/EventData.cc:43
#27 0x00000000004c575c in Viewer::LoadRootFileThread::Run (this=0x3753050) at src/Thread/LoadRootFileThread.cc:45
#28 0x00000000004c6a5c in Viewer::Thread::RunT (this=0x3753050) at src/Thread/Thread.cc:47
#29 0x00000000004c69c4 in Viewer::Thread::PosixCaller (arg=0x3753050) at src/Thread/Thread.cc:19
#30 0x00007f89f50e59ca in start_thread () from /lib/libpthread.so.0
#31 0x00007f89f3b3f70d in clone () from /lib/libc.so.6
#32 0x0000000000000000 in ?? ()

Just to be clear, this problem is only present in ROOT-5.32.00 onwards.

No crash if running in valgrind, how does this improve matters?

Hi,

Did you create a TThread object for each thread and/or initialize TThread?

Is the current ROOT directory (gDirectory) the same for both thread?

Philippe.

Hello,

I’ve tried initialising a TThread, it doesn’t seem to affect things. How do you make the gDirectory different for each thread?

Phil

Hi,

Can you send me a running example showing the problem?

Thanks,
Philippe.