aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Janak Ramakrishnan <janakr@google.com>2016-06-14 17:27:52 +0000
committerGravatar Yue Gan <yueg@google.com>2016-06-15 08:41:43 +0000
commit822ef5e03c7a8dc75bf17edd67b94ffdad51f43f (patch)
treed36fe52219c3c52179391787330e3ec0c6b17254 /src
parent453faa78f8ef0a80146a8e04d3d176f871fd85ae (diff)
Tolerate null variable values in Profiler. This can happen when the build finishes, which calls #clear (via #stop via BlazeRuntime#afterCommand), concurrently with an OOM or other asynchronous crash which invokes CommandCompleteEvent subscribers, which may try to write profiling data.
-- MOS_MIGRATED_REVID=124853610
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/profiler/Profiler.java18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
index 948a4c68fe..7ac8370ffe 100644
--- a/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
+++ b/src/main/java/com/google/devtools/build/lib/profiler/Profiler.java
@@ -41,6 +41,7 @@ import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Logger;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
@@ -117,6 +118,8 @@ import java.util.zip.DeflaterOutputStream;
*/
//@ThreadSafe - commented out to avoid cyclic dependency with lib.util package
public final class Profiler {
+ private static final Logger LOG = Logger.getLogger(Profiler.class.getName());
+
static final int MAGIC = 0x11223344;
// File version number. Note that merely adding new record types in
@@ -733,15 +736,24 @@ public final class Profiler {
}
tasksHistograms[type.ordinal()].addStat((int) TimeUnit.NANOSECONDS.toMillis(duration), object);
- TaskData parent = taskStack.peek();
+ // Store instance fields as local variables so they are not nulled out from under us by #clear.
+ TaskStack localStack = taskStack;
+ Queue<TaskData> localQueue = taskQueue;
+ if (localStack == null || localQueue == null) {
+ // Variables have been nulled out by #clear in between the check the caller made and this
+ // point in the code. Probably due to an asynchronous crash.
+ LOG.severe("Variables null in profiler for " + type + ", probably due to async crash");
+ return;
+ }
+ TaskData parent = localStack.peek();
if (parent != null) {
parent.aggregateChild(type, duration);
}
if (wasTaskSlowEnoughToRecord(type, duration)) {
- TaskData data = taskStack.create(startTime, type, object);
+ TaskData data = localStack.create(startTime, type, object);
data.duration = duration;
if (out != null) {
- taskQueue.add(data);
+ localQueue.add(data);
}
SlowestTaskAggregator aggregator = slowestTasks[type.ordinal()];