c++ executable that is opened by bash, reads, performs analysis, writing a TFile then exits.
c++ executable that is opened by a bash script that lists all files in specified directories, performs analysis, updates all TFiles (one at a time but loops through all files within the single executable) related then exits.
c++ executable that is opened by a bash script that lists all files in specified directories, reads all TFiles related (one at a time but loops through all files within the single executable) then exits.
\break
Runs perfectly fine as it dynamically kills the executable after an individual TFile freeing up resources.
Originally had “Too many open files” issue, but changing making sure to closing and deleting the TFiles in the loop helped. Now runs well.
Declares the following:
TFile*
TObject*
2TH1I*
1TH2I*
TCanvas*
In the beginning, I check for null pointer
TFile * file=NULL;
//Check for zombie
file = new TFile( filename.c_str() , "read");
if ( file==NULL){//file->IsZombie() ){
cout<<"This is a dead file"<<endl;
file->Close();
delete file;
return;
then at the end of the method, I close
TCanvas, TFile and delete TCanvas, TFile and TObject I seem to get the Too many open files error.
I am having trouble understanding how to properly “close” files and how TFile counts as a “file” by bash. I am thinking of changing programs 2 and 3 to similar type as 1 to avoid this problem, but is there another solution? Is there a proper way to close TFiles?
As you’ve seen, right now I close TFile* file by first
file->Close();
then
delete file;
Thank you for your time.
// I should mention that I can go around it with setting ulimit to hard limit, but I rather not because this is more TFile issue rather than number of files that need to be open.
I think you meant to write (to avoid using a nullptr):
TFile * file = nullptr;
//Check for zombie
file = new TFile( filename.c_str() , "read");
if ( file==nullptr) {
cout<<"This is a dead file"<<endl;
return;
} else if (file->IsZombie()) {
cout<<"This is a Zombie file"<<endl;
delete file; // This also does the Close when appropriate.
return;
}
TFile *file = TFile::Open(filename.c_str()); // try to open it for "reading"
if ((!file) || file->IsZombie()) { delete file; return; } // just a precaution
// ...
// ... retrieve and use any objects you need from your "file"
// ...
delete file; // no longer needed ("cleanup")
I actually read one of the posts suggesting using TFile::option rather than to use the constructor, and unfortunately it didn’t change the outcome for me.
Furthermore, I found that if I use the TFile:: option, I get a segment fault if the file does not exist.
However I will try the following:
use nullptr instead of value NULL
delete file as soon as the elements I am looking for has been read.
A quick question though. What if iI am opening the file with “update” option to read, then write new components in it?
Using the null pointer and using the constructor
TFile file* = new TFile(file, “update”);
followed by
file->Close();
delete file;
at the end of the loop so far seems to work so far.
It seemed to have solved the issue but I am getting the same error yet again. I am confused and do not understand beause I did it very carefully. All pointers are kept in their original state until delete, and all pointers are deleted, and the only one TFile* is closed and deleted.
How did TH1::AddDirectory(kFALSE) help?
Furthermore,
TFile *file = TFile::Open(filename.c_str());
yields segment fault whereas
file = new TFile( filename.c_str() , “read”);
does not, if the root file exists. The constructor gives me a chance to check for null pointer before crashing.
TFile *file = TFile::Open(filename.c_str(), "UPDATE"); // open a file for writing
if ((!file) || file->IsZombie()) { delete file; return; } // just a precaution
// ...
// ... retrieve and / or create and use any objects you need
// ...
file->Write(); // make sure everything is really written
delete file; // no longer needed ("cleanup")
Unfortunately, still not working. In fact using the function Tfile::Open crashes the executable way earlier than before when I would use the constructor.
Yes, I have already done that and valgrind gave me 100+ handful of definitely lost referring to the ROOT packages. None of which are coming from my source code, but only from root libraries.
At least valgrind says it’s an issue with root 6.14. I doubt 6.16 will be any better.
This is very unusual. For local files the 2 call do essentially the same. When using TFile::Open what is the stack trace at the crash? When using TFile::Open was is the valgrind error reported (don’t forget to use --suppressions=$ROOTSYS/etc/valgrind-root.supp)
I will use the suppression option, I’ve actually not use that for valgrind. I will get back to you in a while with the stack trace because I am currently working on a work-around which seems to work for now.
I think I described it wrong above,
TFile *file = TFile::Open(filename.c_str(), "read" );
//Yields segment fault IFF root file for filename.c_str() does not exist.
TFile *file = new TFile( filename.c_str() , “read”);
//Yields error throw IF root file for filename.c_str() does not exist.
If I use the former, the executable crashes with a segement fault in case the filename does not give a file address. If I use the latter