Repository navigation
Fix incorrect exit code for asprof when running in collect mode - #1623
Conversation
| _inverted = true; | ||
|
|
||
| CASE("_collect") | ||
| _collect = true; |
There was a problem hiding this comment.
The problem I kept hitting, is that profiler has different behavior depending on various condition, I wanted to keep the behaviors untouched as is,
For example, the following won't generate a log
asprof start -cpu -f out.html 1234
asprof stop 1234
while, this will generate a log
asprof start -cpu -f out.html 1234
VMDeath
asprof stop 1234
so a "secret" made sense to not effect existing behaviors
There was a problem hiding this comment.
asprof is nothing but a binary script that loads profiler library in a target process and invokes commands on it. It could as well be a shell script or a custom program that does a similar thing. And I know people use custom scripts. A hidden option in asprof will not help them.
There was a problem hiding this comment.
I've updated my approach to be determined on the usage,
If the user starts the asprof with a file, then it's fine for the stop call to fail on termination & that failed stop can be considered a success (the VMDeath would have done the dump for the user)
So the user can address this race in any custom script by providing the output file in both start & stop as the asprof collect is currently doing ee54ad2
| Error Profiler::dump(Writer& out, Arguments& args) { | ||
| MutexLocker ml(_state_lock); | ||
| if (_state != IDLE && _state != RUNNING) { | ||
| if (args._collect && _state == TERMINATED) { |
There was a problem hiding this comment.
OK, stopping profiler in TERMINATED state is not an error. But why should behavior differ when running asprof standalone vs. from a script? And why is this check in dump, if asprof invokes stop?
There was a problem hiding this comment.
It's mostly my personal interpretation on how the profiler should behave
And why is this check in dump, if asprof invokes stop
The fall through from stop to dump makes having this check in stop redundant
The only edge case would be if user called stop with no output file, but then it will be reported as a failure with a clear error Profiler is not active
why should behavior differ when running asprof standalone vs. from a script
In asprof "collect" mode both start & end are called with output file, which means we're guaranteed for the profiler to dump the profile on disk via VMDeath + global args
However for a regular start/stop commands, the dump isn't guaranteed which is arguably an error
asprof start -e cpu 915
asprof stop -f out.html
There was a problem hiding this comment.
Again, this is not specific to asprof; asprof is just a wrapper.
It should be a decision of libasyncProfiler to return an error or not.
There was a problem hiding this comment.
I've updated my approach to be determined on the usage,
If the user starts the asprof with a file, then it's fine for the stop call to fail on termination & that failed stop can be considered a success (the VMDeath would have done the dump for the user)
So the user can address this race in any custom script by providing the output file in both start & stop as the asprof collect is currently doing ee54ad2
|
|
||
| static ProfilingWindow profiling_window; | ||
|
|
||
| static const char* _start_file = NULL; |
There was a problem hiding this comment.
This is unnecessary. If _start_file comes from _global_args, then you can access it via _global_args. But if it comes from elsewhere, the pointer will be invalid.
There was a problem hiding this comment.
that make sense
| Error Profiler::dump(Writer& out, Arguments& args) { | ||
| MutexLocker ml(_state_lock); | ||
| if (_state != IDLE && _state != RUNNING) { | ||
| if (_state == TERMINATED && _start_file != NULL && args.rawFile() != NULL && strcmp(_start_file, args.rawFile()) == 0) { |
There was a problem hiding this comment.
This is a bit better than _collect, but is still a hack. I was thinking of something simpler, like always returning Error::OK for stop command if we are in TERMINATED. Although this is not fully accurate, I can't imagine a case when this is a real problem.
There was a problem hiding this comment.
Alright, what about this hack:
if (_state == TERMINATED && args.hasTemporaryLog()) {
return Error::OK;
}
The effect is the same as in your first revision, just with less code changes.
There was a problem hiding this comment.
like always returning Error::OK for stop command if we are in TERMINATED
The real problematic part is the dump command not the stop & the dump will fail if profiler is terminated (Not safe to access JNI & JVMTI)
IMO if the output selected by the user isn't dumped, then that should be considered a failure, what are you thoughts on this @apangin
From this perspective the only way for the profiler to dump it correclty, is for the user to provide the output file on the start command, hence my hack
Alright, what about this hack:
if (_state == TERMINATED && args.hasTemporaryLog()) {
return Error::OK;
}
The effect is the same as in your first revision, just with less code changes.
This will also mark normal stops as a success even if the profiler didn't really write the profiles, which is wrong
asprof start -e cpu 1234
sleep 10
asprof stop -f out.html 1234 <--- this hit the race condition & unable to generate the out.html
There was a problem hiding this comment.
OK, agreed - let's proceed with the file trick as I don't see a simple way to solve this cleanly without redesigning the entire protocol.
A good news is that it will be a tiny local change: all you need is to compare args._file to _global_args._file.
Description
This change tackles one of the race conditions described in #1622
Being the race condition of what will execute first, the
stopat the end of the collect command or theVMDeathhookIf
VMDeathis executed first, then it will stop the profiler, dump the profile & proceed to terminate the profiler,Following that the
stopcommand will fail as the profiler is terminatedIn this change, an internal flag is passed from
asprofto the profiler, as to mark the current stop command as one coming from collect (Other stops commands should still fail) as to give it special handlingRelated issues
#1622
Motivation and context
asprof shouldn't have a non zero exit code from VMDeath
How has this been tested?
manual testing
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.