From d17467e3bf9ff0408d201b960af71939b55b873b Mon Sep 17 00:00:00 2001 From: laszlocsomor Date: Tue, 10 Jul 2018 06:11:18 -0700 Subject: Bazel server, tools: ensure Writers are closed Follow-up to commit 09d20311d982606093ed881d779bb05a5ee70ed3. Use try-with-resources to ensure Writer objects are closed eagerly. Eagerly closing Writers avoids hanging on to file handles until the garbage collector finalizes the object, meaning Bazel on Windows (and other processes) can delete or mutate these files. Hopefully this avoids intermittent file deletion errors that sometimes occur on Windows. See https://github.com/bazelbuild/bazel/issues/5512 RELNOTES: none PiperOrigin-RevId: 203934471 --- .../bazel/repository/RepositoryResolvedModule.java | 4 +- .../devtools/build/lib/profiler/Profiler.java | 59 ++++++++-------------- 2 files changed, 23 insertions(+), 40 deletions(-) (limited to 'src/main') diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryResolvedModule.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryResolvedModule.java index d4d4849e6c..de53082f8e 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryResolvedModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryResolvedModule.java @@ -60,13 +60,11 @@ public final class RepositoryResolvedModule extends BlazeModule { @Override public void afterCommand() { if (resolvedFile != null) { - try { - Writer writer = Files.newWriter(new File(resolvedFile), StandardCharsets.UTF_8); + try (Writer writer = Files.newWriter(new File(resolvedFile), StandardCharsets.UTF_8)) { writer.write( EXPORTED_NAME + " = " + Printer.getPrettyPrinter().repr(resultBuilder.build()).toString()); - writer.close(); } catch (IOException e) { logger.warning("IO Error writing to file " + resolvedFile + ": " + e); } 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 2e971fedfa..47008de2be 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 @@ -31,7 +31,6 @@ import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.Writer; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -887,30 +886,21 @@ public final class Profiler { /** Writes the profile in the binary Bazel profile format. */ private static class BinaryFormatWriter extends FileWriter { - private final DataOutputStream out; + private final OutputStream outStream; private final long profileStartTime; private final String comment; - BinaryFormatWriter( - OutputStream out, - long profileStartTime, - String comment) { + BinaryFormatWriter(OutputStream outStream, long profileStartTime, String comment) { // Wrapping deflater stream in the buffered stream proved to reduce CPU consumption caused by // the write() method. Values for buffer sizes were chosen by running small amount of tests // and identifying point of diminishing returns - but I have not really tried to optimize // them. - this.out = - new DataOutputStream( - new BufferedOutputStream( - new DeflaterOutputStream( - // the DeflaterOutputStream has its own output buffer of 65k, chosen at random - out, new Deflater(Deflater.BEST_SPEED, false), 65536), - 262144)); // buffer size, basically chosen at random + this.outStream = outStream; this.profileStartTime = profileStartTime; this.comment = comment; } - private void writeHeader() throws IOException { + private static void writeHeader(DataOutputStream out, String comment) throws IOException { out.writeInt(MAGIC); // magic out.writeInt(VERSION); // protocol_version out.writeUTF(comment); @@ -931,8 +921,16 @@ public final class Profiler { public void run() { try { boolean receivedPoisonPill = false; - try { - writeHeader(); + try (DataOutputStream out = + new DataOutputStream( + new BufferedOutputStream( + new DeflaterOutputStream( + // the DeflaterOutputStream has its own output buffer of 65k, chosen at + // random + outStream, new Deflater(Deflater.BEST_SPEED, false), 65536), + // buffer size, basically chosen at random + 262144))) { + writeHeader(out, comment); // Allocate the sink once to avoid GC ByteBuffer sink = ByteBuffer.allocate(1024); ObjectDescriber describer = new ObjectDescriber(); @@ -974,14 +972,8 @@ public final class Profiler { } receivedPoisonPill = true; out.writeInt(EOF_MARKER); - out.close(); } catch (IOException e) { this.savedException = e; - try { - out.close(); - } catch (IOException e2) { - // ignore it - } if (!receivedPoisonPill) { while (queue.take() != POISON_PILL) { // We keep emptying the queue, but we can't write anything. @@ -996,16 +988,11 @@ public final class Profiler { /** Writes the profile in Json Trace file format. */ private static class JsonTraceFileWriter extends FileWriter { - private final Writer out; + private final OutputStream outStream; private final long profileStartTimeNanos; - JsonTraceFileWriter( - OutputStream out, - long profileStartTimeNanos) { - this.out = - // The buffer size of 262144 is chosen at random. We might also want to use compression - // in the future. - new OutputStreamWriter(new BufferedOutputStream(out, 262144), StandardCharsets.UTF_8); + JsonTraceFileWriter(OutputStream outStream, long profileStartTimeNanos) { + this.outStream = outStream; this.profileStartTimeNanos = profileStartTimeNanos; } @@ -1018,7 +1005,11 @@ public final class Profiler { public void run() { try { boolean receivedPoisonPill = false; - try { + try (OutputStreamWriter out = + // The buffer size of 262144 is chosen at random. We might also want to use compression + // in the future. + new OutputStreamWriter( + new BufferedOutputStream(outStream, 262144), StandardCharsets.UTF_8)) { out.append("["); boolean first = true; TaskData data; @@ -1052,14 +1043,8 @@ public final class Profiler { } receivedPoisonPill = true; out.append("]"); - out.close(); } catch (IOException e) { this.savedException = e; - try { - out.close(); - } catch (IOException e2) { - // ignore it - } if (!receivedPoisonPill) { while (queue.take() != POISON_PILL) { // We keep emptying the queue, but we can't write anything. -- cgit v1.2.3