diff options
author | Jean-Philippe Lesot <jplesot@google.com> | 2015-03-31 16:33:47 +0200 |
---|---|---|
committer | Jean-Philippe Lesot <jplesot@google.com> | 2015-03-31 16:33:47 +0200 |
commit | 9d912214d64dc06cd485bffd66fe6d3b0d6defbf (patch) | |
tree | c7353d946486253307fc35ee0a0e04fb4899057c /jack-server | |
parent | 2123d170c6ff3920d916de492a9fcf06caaf81a4 (diff) | |
download | toolchain_jack-9d912214d64dc06cd485bffd66fe6d3b0d6defbf.tar.gz toolchain_jack-9d912214d64dc06cd485bffd66fe6d3b0d6defbf.tar.bz2 toolchain_jack-9d912214d64dc06cd485bffd66fe6d3b0d6defbf.zip |
Add a support for opening file with timeout in Jack simple server
Change-Id: I560af413992a38711b5bd0053cf8fe0efddeceab
Diffstat (limited to 'jack-server')
-rw-r--r-- | jack-server/src/com/android/jack/server/JackSimpleServer.java | 116 |
1 files changed, 99 insertions, 17 deletions
diff --git a/jack-server/src/com/android/jack/server/JackSimpleServer.java b/jack-server/src/com/android/jack/server/JackSimpleServer.java index 15985b63..63936530 100644 --- a/jack-server/src/com/android/jack/server/JackSimpleServer.java +++ b/jack-server/src/com/android/jack/server/JackSimpleServer.java @@ -18,9 +18,13 @@ package com.android.jack.server; import com.google.common.base.Joiner; +import com.android.sched.util.ConcurrentIOException; import com.android.sched.util.config.cli.TokenIterator; import com.android.sched.util.file.InputStreamFile; +import com.android.sched.util.file.NoSuchFileException; +import com.android.sched.util.file.NotFileException; import com.android.sched.util.file.OutputStreamFile; +import com.android.sched.util.file.WrongPermissionException; import com.android.sched.util.findbugs.SuppressFBWarnings; import com.android.sched.util.location.NoLocation; import com.android.sched.util.log.tracer.probe.MemoryBytesProbe; @@ -37,8 +41,11 @@ import org.simpleframework.transport.connect.Connection; import org.simpleframework.transport.connect.SocketConnection; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintStream; import java.lang.management.CompilationMXBean; import java.lang.management.GarbageCollectorMXBean; @@ -65,12 +72,14 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.CheckForNull; +import javax.annotation.Nonnegative; import javax.annotation.Nonnull; /** @@ -313,18 +322,18 @@ public class JackSimpleServer { logger.log(Level.INFO, "Open standard output '" + command[CMD_IDX_OUT] + "'"); try { - out = new OutputStreamFile(command[CMD_IDX_OUT]).getPrintStream(); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + out = new FifoStreamFile(command[CMD_IDX_OUT]).getPrintStream(10000); + } catch (IOException | TimeoutException e) { + logger.log(Level.SEVERE, e.getMessage()); response.setStatus(Status.BAD_REQUEST); return; } logger.log(Level.INFO, "Open standard error '" + command[CMD_IDX_ERR] + "'"); try { - err = new OutputStreamFile(command[CMD_IDX_ERR]).getPrintStream(); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + err = new FifoStreamFile(command[CMD_IDX_ERR]).getPrintStream(10000); + } catch (IOException | TimeoutException e) { + logger.log(Level.SEVERE, e.getMessage()); response.setStatus(Status.BAD_REQUEST); return; } @@ -653,8 +662,8 @@ public class JackSimpleServer { System.exit(1); } - private static volatile PrintStream out = null; - private static volatile InputStream in = null; + private static volatile PrintStream unblockOut = null; + private static volatile InputStream unblockIn = null; private static void unblock(@Nonnull final String name) { logger.log(Level.INFO, "Trying to unblock '" + name + "'"); @@ -666,7 +675,7 @@ public class JackSimpleServer { @Override public void run() { try { - in = new InputStreamFile(name).getInputStream(); + unblockIn = new InputStreamFile(name).getInputStream(); } catch (IOException e) { // Best effort } @@ -675,7 +684,7 @@ public class JackSimpleServer { thread.start(); try { - out = new OutputStreamFile(name).getPrintStream(); + unblockOut = new OutputStreamFile(name).getPrintStream(); } catch (IOException e) { // Best effort } @@ -689,19 +698,86 @@ public class JackSimpleServer { } } - if (out != null) { - out.close(); + if (unblockOut != null) { + unblockOut.close(); } - if (in != null) { + if (unblockIn != null) { try { - in.close(); + unblockIn.close(); } catch (IOException e) { // Best effort } } } + private static class FifoStreamFile extends OutputStreamFile { + @CheckForNull + private volatile OutputStream tmp; + + public FifoStreamFile(@Nonnull String name) throws WrongPermissionException, NotFileException { + super(name); + // Check also read permission, writing without reader is useless + checkPermissions(file, location, Permission.READ); + } + + @Nonnull + public synchronized OutputStream getOutputStream(@Nonnegative int timeout) + throws TimeoutException { + if (stream == null) { + Thread thread = new Thread() { + @Override + public void run() { + try { + tmp = new FileOutputStream(file, isInAppendMode()); + } catch (FileNotFoundException e) { + throw new ConcurrentIOException(e); + } + } + }; + thread.setDaemon(true); + thread.start(); + + try { + thread.join(timeout); + } catch (InterruptedException e) { + // If interrupted, abort timeout + } + + if (tmp == null) { + // Try to unblock thread above + try { + // TODO(jack-team) The open can block again ... + new InputStreamFile(getPath()).getInputStream().close(); + } catch (NotFileException | WrongPermissionException | NoSuchFileException e) { + // Already check + throw new ConcurrentIOException(e); + } catch (IOException e) { + // Error during close, nothing to do + } + + throw new TimeoutException("Cannot open " + location.getDescription() + " for " + timeout + + " ms"); + } + + stream = tmp; + } + + assert stream != null; + return stream; + } + + @Nonnull + public synchronized PrintStream getPrintStream(@Nonnegative int timeout) + throws TimeoutException { + if (printer == null) { + printer = new PrintStream(getOutputStream(timeout)); + } + + return printer; + } + } + private static void startTimer() { lock.lock(); try { @@ -766,9 +842,15 @@ public class JackSimpleServer { // Get current UserPrincipal assert path != null; - java.nio.file.Path tmp = Files.createTempFile(path, "jss-", "-check"); - UserPrincipal user = Files.getOwner(tmp); - Files.delete(tmp); + UserPrincipal user; + java.nio.file.Path tmp; + try { + tmp = Files.createTempFile(path, "jss-", "-check"); + user = Files.getOwner(tmp); + Files.delete(tmp); + } catch (IOException e) { + throw new SecurityException("Cannot create/delete file in '" + path + "' to check security"); + } // Check parent directory UserPrincipal owner = Files.getOwner(path); |