summaryrefslogtreecommitdiff
path: root/main/client/src/MillClientMain.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/client/src/MillClientMain.java')
-rw-r--r--main/client/src/MillClientMain.java162
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();
+ }
+ }
+}