diff options
Diffstat (limited to 'main/client/src/MillClientMain.java')
-rw-r--r-- | main/client/src/MillClientMain.java | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/main/client/src/MillClientMain.java b/main/client/src/MillClientMain.java new file mode 100644 index 00000000..3857caff --- /dev/null +++ b/main/client/src/MillClientMain.java @@ -0,0 +1,162 @@ +package mill.main.client; + +import org.scalasbt.ipcsocket.*; + +import java.io.*; +import java.net.Socket; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.channels.FileChannel; +import java.util.*; + +public class MillClientMain { + static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,URISyntaxException{ + String[] selfJars = System.getProperty("MILL_CLASSPATH").split(","); + + List<String> l = new ArrayList<>(); + List<String> vmOptions = new ArrayList<>(); + l.add("java"); + final Properties props = System.getProperties(); + for(final String k: props.stringPropertyNames()){ + if (k.startsWith("MILL_") && !"MILL_CLASSPATH".equals(k)) { + vmOptions.add("-D" + k + "=" + props.getProperty(k)); + } + } + if (setJnaNoSys) { + vmOptions.add("-Djna.nosys=true"); + } + if(!Util.isWindows){ + l.addAll(vmOptions); + } else { + final File vmOptionsFile = new File(lockBase, "vmoptions"); + try (PrintWriter out = new PrintWriter(vmOptionsFile)) { + for(String opt: vmOptions) + out.println(opt); + } + l.add("-XX:VMOptionsFile=" + vmOptionsFile.getCanonicalPath()); + } + l.add("-cp"); + l.add(String.join(File.pathSeparator, selfJars)); + l.add("mill.main.MillServerMain"); + l.add(lockBase); + + new ProcessBuilder() + .command(l) + .redirectOutput(new java.io.File(lockBase + "/logs")) + .redirectError(new java.io.File(lockBase + "/logs")) + .start(); + } + public static void main(String[] args) throws Exception{ + System.exit(main0(args)); + } + public static int main0(String[] args) throws Exception{ + boolean setJnaNoSys = System.getProperty("jna.nosys") == null; + Map<String, String> env = System.getenv(); + if (setJnaNoSys) { + System.setProperty("jna.nosys", "true"); + } + int index = 0; + while (index < 5) { + index += 1; + String lockBase = "out/mill-worker-" + index; + new java.io.File(lockBase).mkdirs(); + + try(RandomAccessFile lockFile = new RandomAccessFile(lockBase + "/clientLock", "rw"); + FileChannel channel = lockFile.getChannel(); + java.nio.channels.FileLock tryLock = channel.tryLock(); + Locks locks = Locks.files(lockBase)){ + if (tryLock != null) { + int exitCode = MillClientMain.run( + lockBase, + new Runnable() { + @Override + public void run() { + try{ + initServer(lockBase, setJnaNoSys); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + }, + locks, + System.in, + System.out, + System.err, + args, + env + ); + return exitCode; + } + } finally{ + + } + } + throw new Exception("Reached max process limit: " + 5); + } + + public static int run(String lockBase, + Runnable initServer, + Locks locks, + InputStream stdin, + OutputStream stdout, + OutputStream stderr, + String[] args, + Map<String, String> env) throws Exception{ + + try(FileOutputStream f = new FileOutputStream(lockBase + "/run")){ + f.write(System.console() != null ? 1 : 0); + Util.writeString(f, System.getProperty("MILL_VERSION")); + Util.writeArgs(args, f); + Util.writeMap(env, f); + } + + boolean serverInit = false; + if (locks.processLock.probe()) { + serverInit = true; + initServer.run(); + } + while(locks.processLock.probe()) Thread.sleep(3); + + // Need to give sometime for Win32NamedPipeSocket to work + // if the server is just initialized + if (serverInit && Util.isWindows) Thread.sleep(1000); + + Socket ioSocket = null; + + long retryStart = System.currentTimeMillis(); + + while(ioSocket == null && System.currentTimeMillis() - retryStart < 1000){ + try{ + ioSocket = Util.isWindows? + new Win32NamedPipeSocket(Util.WIN32_PIPE_PREFIX + new File(lockBase).getName()) + : new UnixDomainSocket(lockBase + "/io"); + }catch(Throwable e){ + Thread.sleep(1); + } + } + if (ioSocket == null){ + throw new Exception("Failed to connect to server"); + } + + InputStream outErr = ioSocket.getInputStream(); + OutputStream in = ioSocket.getOutputStream(); + ProxyStreamPumper outPump = new ProxyStreamPumper(outErr, stdout, stderr); + InputPumper inPump = new InputPumper(stdin, in, true); + Thread outThread = new Thread(outPump); + outThread.setDaemon(true); + Thread inThread = new Thread(inPump); + inThread.setDaemon(true); + outThread.start(); + inThread.start(); + + locks.serverLock.await(); + + try(FileInputStream fos = new FileInputStream(lockBase + "/exitCode")){ + return Integer.parseInt(new BufferedReader(new InputStreamReader(fos)).readLine()); + } catch(Throwable e){ + return 1; + } finally{ + ioSocket.close(); + } + } +} |