-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Teach TFileMerger to work with TFile* handles. #1073
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Starting build on |
ca32b2e to
97a7c45
Compare
|
Starting build on |
|
Build failed on slc6/gcc49. Failing tests: |
|
Build failed on ubuntu14/native. Failing tests: |
|
Build failed on centos7/gcc49. Failing tests: |
|
Build failed on mac1012/native. Failing tests: |
|
Build failed on slc6/gcc62. Failing tests: |
| ASSERT_TRUE(t != nullptr); | ||
|
|
||
| double d; | ||
| t->SetBranchAddress(name, &d); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting branch address to a stack address requires to either call t->ResetBranchAddresses(); or delete the TTree (otherwise it is technically in an invalid state).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean that file.Get(name) allocates an object and it is the user's responsibility to deallocate it? If yes, I assume I can transform it into a unique_ptr and would that work well with having a t->ResetBranchAddresses();?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that mean that file.Get(name) allocates an object and it is the user's responsibility to deallocate it?
In the case of a TTree, the point is an implicit shared pointer. You can delete it (and the TFile will be informed) and you can let the TFile delete it (but your are not directly inform when it does unless you are registered in the list of cleanups).
If yes, I assume I can transform it into a unique_ptr
Yes, you can as long as you make sure that the lifetime of the unique_ptr is less or equal to the litetime of the TFile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be done.
|
|
||
| static void CreateATuple(TMemFile &file, const char *name, double value) | ||
| { | ||
| auto mytree = new TTree(name, "A tree"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to be (guaranteed to be) consistent, you may want to add
mytree->SetDirectory(&file);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... would that mean I will have to reset it in the end of that function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... would that mean I will have to reset it in the end of that function?
Why? Because "file" in all your use case is already the current directory, adding SetDirectory would be a nop however if for somewhere 'file' is not the current directory at the time CreateATuple then the behavior of the function would not be what you expects. (it would attach the TTree to another file and thus the file.Write at the end would not store the TTree at alll).
And actually that reminds me we have a new constructor to use instead of (new + SetDirectory):
auto mytree = new TTree(name, "A tree", &file);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
io/io/test/TFileMergerTests.cxx
Outdated
| CreateATuple(b, "b_tree", 2.); | ||
|
|
||
| TFileMerger merger; | ||
| auto output = new TMemFile("output.root", "CREATE"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not having output being a unique_ptr? (Maybe using std::make_unique :) )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, the TMemFile got deleted by the merger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but then you do:
merger.OutputFile(std::unique_ptr<TFile>(output));
So I don't see the difference :) (and yes ownership needs to pass for this function to the TMemFile ....
|
Starting build on |
|
Build failed on ubuntu14/native. Failing tests: |
|
Build failed on centos7/gcc49. Failing tests: |
|
Build failed on mac1012/native. Failing tests: |
|
Build failed on slc6/gcc49. Failing tests: |
|
Build failed on slc6/gcc62. Failing tests: |
1d22da1 to
3a74914
Compare
|
Starting build on |
vgvassilev
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments should be addressed.
3a74914 to
d56481c
Compare
|
Starting build on |
|
Build failed on slc6/gcc49. Failing tests: |
|
Build failed on centos7/gcc49. Failing tests: |
|
Build failed on mac1012/native. Warnings:
And 10 more Failing tests: |
|
Build failed on ubuntu14/native. Failing tests: |
Maybe, maybe not. This is the list of cleanups. |
|
Well we need a stacktrace of the crash to correlate. E.g. the |
|
here is a stacktrace. I think an interesting piece of information would be the name of the |
This usually happens when a thread has/had a gDirectory pointing to a file/directory and that this directory is deleted by another thread. |
|
Is there a way to understand if those race conditions pre-existing to this patch? |
|
The issue being pre-existing is getting less and less likely, given the info here... But I think Danilo and Enrico know this kind of issue from previous code versions; I bet you can solve this with their help!
|
|
yeah i'm here to help. in addition to the suggestions above, since you said that the crash disappears if you run the problematic test in isolation, it might be interesting to check whether the different threads have a |
440caba to
c4ed4b9
Compare
|
Starting build on |
This patch allows TFileMerger to work with externally created TFile-s. Being able to control the creation of the TFile objects give us a chance to use in-memory files. This is very helpful in benchmarking when we want to simulate fast disks or we just want to avoid disk wearout.
c4ed4b9 to
e8a02a7
Compare
|
Starting build on |
|
Build failed on slc6/gcc62. Errors:
|
|
@phsft-bot build! Seems like the failure is infrastructure but let's retrigger. |
|
Starting build on |
|
I found the race condition, it was in the way we created the output @dpiparo shall I dismiss your request for changes as they are already in? |
|
@vgvassilev if the changes are addressed, for sure. Thanks! |
The requests for changes were addressed.
| std::function<void(void)> fCallback; //< Callback for when data is removed from queue | ||
|
|
||
| ClassDef(TBufferMerger, 0); | ||
| ClassDef(TBufferMerger, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why change this? This only matters for classes that are streamed. This should have remained as 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, when you have a ClassDef and you change data members you also should bump the ClassDef version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, when you have a ClassDef and you change data members you also should bump the ClassDef version.
only when you change a persistent member :) ... and version == 0 means that all data members are implicitly marked transient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall I revert it back to 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done. I don't understand how is that a non persistent data member but you are the expert.
Humm ... when the class version is set to zero then all the data member of the class are consider transient ... i.e. non-persistent .... When you increase to the version to 1, this turned implicitly all the data member to become persistent. |
|
...by the way, why does TFileMerger need a `ClassDef` in the first place?
…On Thu, Oct 5, 2017 at 3:08 PM, Philippe Canal ***@***.***> wrote:
Ok, done. I don't understand how is that a non persistent data member but
you are the expert.
Humm ... when the class version is set to zero then *all* the data member
of the class are consider transient ... i.e. non-persistent .... When you
increase to the version to 1, this turned implicitly all the data member to
become persistent.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1073 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AKfU-nEGiaaVjwRDi9gIw3FcpqW7Ep8Cks5spNTZgaJpZM4Pn4OQ>
.
|
|
Any class that inherits from TObject must have a ClassDef otherwise some the routines are inconsistent (like IsA() ). |
This patch allows TFileMerger to work with externally created TFile-s. Being
able to control the creation of the TFile objects give us a chance to use
in-memory files. This is very helpful in benchmarking when we want to simulate
fast disks or we just want to avoid disk wearout.