I’m not sure whether this is a bug or not (which is why I’m posting it here), but it seems to me, that root’s build-in atexit-function somehow corrupts open root-files so that atexit-functions that are e.g. trying to save all open histograms to these files fail if they are executed after the root atexit-function.
The problem (bug?) is that even though it’s impossible to write the histograms to the open output-file without a segmentation violation the files are still open and it’s possible to list they’re content.
The problem disappears if the user registers his own atexit-function after creating an other TFile (instead of before) so that this atexit-function is executed before the root atexit-function is executed. It also disappears if one writes anything into the open outputfile before exiting.
So maybe the root atexit-function ought to be changed so that either the open files are not damaged or that one can at least check for this (e.g. by setting the status to closed)?
the still open TFile’s are closed when TROOT goes out of scope and is controlled by the C++ run-time system. The atexit calls are done after the C++ run-time has finished deleting any global objects. Hence. don’t try to do anything with ROOT files during atexit execution.
A few remarks: according to the c+±standard objects with static storage duration (which includes a global static pointer to a root-file) are deleted after any atexit-function was called (if the atexit function was registered after the object created).
The root-file itself is created on the heap and as such shouldn’t be deleted until after any atexit-function.
The program did work with root 5.08 and doesn’t work anymore with root 5.24 so it can’t be a problem of the c++ run-time.
The program also work if the atexit function is registered after creating the root-file. Since the atexit-functions are executed in the reverse order, it seems like the atexit function associated with the root-file is the problem.
So it seems to me that something was changed in the atexit-function since version 5.08 which makes it impossible to write to root-files in later atexit-functions though IsOpen()-function still returns true.
all open files are possibly closed in the following order:
- in TUnixSystem::Exit() (called from .q in interactive session or
- in TROOT::~TROOT() when global gROOT goes out of scope
- in CleanUpROOTAtExit() (was registered in TROOT::TROOT())
if gROOT is still active
To analyse what is going on just before terminating set gDebug=1 so all TFile dtors print info and put a print in your atexit() functions. You could also add a gSystem->StackTrace() call in the ~TFile.
the program is compiled and gROOT still exists (at least a call gROOT->GetListOfFiles()->ls() still works). But the problem I’m having is not that the file is getting deleted before I write (outfile->IsOpen() returns true in the atexit-function), but that I can’t write anything to the file without getting a segmentation violation.
I’ve appended a short example file where this problem occurs. Setting the gDebug=1 shows that the destructors are all called after the atexit-function.
The example works if one switches the atexit(myatexit)-line with the new TFfile line.
Maybe this helps to explain my problem here: the file is not yet deleted but it’s impossible to write into said file.
BTW, this problem also goes away if one were to create another histogram and write it to file inside the main function so this seems to only affect files that are empty at the moment that std::exit() is called.
MyAtExit.c (686 Bytes)