Skip to content

Commit

Permalink
WIP keep mill server alive if you Ctrl-C during --watch (#339)
Browse files Browse the repository at this point in the history
* wip

* Clean up more resources in the Mill client after every command

* catch and ignore SIGINT in Mill server to make it survive Ctrl-C on the client
  • Loading branch information
lihaoyi authored May 19, 2018
1 parent b03cf74 commit a7cb99f
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 87 deletions.
4 changes: 2 additions & 2 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,10 @@ def launcherScript(shellJvmArgs: Seq[String],

s"""case "$$1" in
| -i | --interactive )
| ${java("mill.Main")}
| ${java("mill.MillMain")}
| ;;
| *)
| ${java("mill.main.client.Main")}
| ${java("mill.main.client.MillClientMain")}
| ;;
|esac""".stripMargin
},
Expand Down
3 changes: 2 additions & 1 deletion main/client/src/mill/main/client/Lock.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package mill.main.client;
public abstract class Lock{
public abstract class Lock implements AutoCloseable{
abstract public Locked lock() throws Exception;
abstract public Locked tryLock() throws Exception;

public void await() throws Exception{
lock().release();
}
Expand Down
20 changes: 19 additions & 1 deletion main/client/src/mill/main/client/Locks.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.nio.channels.FileChannel;
import java.util.concurrent.locks.ReentrantLock;

public class Locks{
public class Locks implements AutoCloseable{
public Lock processLock;
public Lock serverLock;
public Lock clientLock;
Expand All @@ -24,6 +24,13 @@ public static Locks memory(){
this.clientLock = new MemoryLock();
}};
}

@Override
public void close() throws Exception {
processLock.close();
serverLock.close();
clientLock.close();
}
}
class FileLocked implements Locked{
private java.nio.channels.FileLock lock;
Expand Down Expand Up @@ -61,6 +68,12 @@ public boolean probe()throws Exception{
return true;
}
}

@Override
public void close() throws Exception {
raf.close();
chan.close();
}
}
class MemoryLocked implements Locked{
java.util.concurrent.locks.Lock l;
Expand All @@ -86,4 +99,9 @@ public Locked tryLock() {
if (innerLock.tryLock()) return new MemoryLocked(innerLock);
else return null;
}

@Override
public void close() throws Exception {
innerLock.unlock();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
import java.nio.channels.FileChannel;
import java.util.*;

public class Main {
public class MillClientMain {
static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,URISyntaxException{
ArrayList<String> selfJars = new ArrayList<String>();
ClassLoader current = Main.class.getClassLoader();
ClassLoader current = MillClientMain.class.getClassLoader();
while(current != null){
if (current instanceof java.net.URLClassLoader) {
URL[] urls = ((java.net.URLClassLoader) current).getURLs();
Expand All @@ -38,7 +38,7 @@ static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,
}
l.add("-cp");
l.add(String.join(File.pathSeparator, selfJars));
l.add("mill.main.ServerMain");
l.add("mill.main.MillServerMain");
l.add(lockBase);

new java.lang.ProcessBuilder()
Expand All @@ -48,6 +48,9 @@ static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,
.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) {
Expand All @@ -58,33 +61,35 @@ public static void main(String[] args) throws Exception{
index += 1;
String lockBase = "out/mill-worker-" + index;
new java.io.File(lockBase).mkdirs();
RandomAccessFile lockFile = new RandomAccessFile(lockBase + "/clientLock", "rw");
FileChannel channel = lockFile.getChannel();
java.nio.channels.FileLock tryLock = channel.tryLock();
if (tryLock == null) {
lockFile.close();
channel.close();
} else {
int exitCode = Main.run(
lockBase,
new Runnable() {
@Override
public void run() {
try{
initServer(lockBase, setJnaNoSys);
}catch(Exception e){
throw new RuntimeException(e);

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.files(lockBase),
System.in,
System.out,
System.err,
args,
env
);
System.exit(exitCode);
},
locks,
System.in,
System.out,
System.err,
args,
env
);
return exitCode;
}
} finally{

}
}
throw new Exception("Reached max process limit: " + 5);
Expand All @@ -99,12 +104,12 @@ public static int run(String lockBase,
String[] args,
Map<String, String> env) throws Exception{

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);
f.close();
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()) {
Expand All @@ -120,6 +125,7 @@ public static int run(String lockBase,
Socket ioSocket = null;

long retryStart = System.currentTimeMillis();

while(ioSocket == null && System.currentTimeMillis() - retryStart < 1000){
try{
ioSocket = Util.isWindows?
Expand All @@ -146,16 +152,12 @@ public static int run(String lockBase,

locks.serverLock.await();

try{
return Integer.parseInt(
new BufferedReader(
new InputStreamReader(
new FileInputStream(lockBase + "/exitCode")
)
).readLine()
);
try(FileInputStream fos = new FileInputStream(lockBase + "/exitCode")){
return Integer.parseInt(new BufferedReader(new InputStreamReader(fos)).readLine());
} catch(Throwable e){
return 1;
} finally{
ioSocket.close();
}
}
}
Expand Down
11 changes: 7 additions & 4 deletions main/src/mill/Main.scala → main/src/mill/MillMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import io.github.retronym.java9rtexport.Export
import mill.eval.Evaluator
import mill.util.DummyInputStream

object Main {
object MillMain {

def main(args: Array[String]): Unit = {
val as = args match {
Expand All @@ -23,7 +23,8 @@ object Main {
System.in,
System.out,
System.err,
System.getenv().asScala.toMap
System.getenv().asScala.toMap,
b => ()
)
System.exit(if(result) 0 else 1)
}
Expand All @@ -34,7 +35,8 @@ object Main {
stdin: InputStream,
stdout: PrintStream,
stderr: PrintStream,
env: Map[String, String]): (Boolean, Option[Evaluator.State]) = {
env: Map[String, String],
setIdle: Boolean => Unit): (Boolean, Option[Evaluator.State]) = {
import ammonite.main.Cli

val removed = Set("predef-code", "no-home-predef")
Expand Down Expand Up @@ -103,7 +105,8 @@ object Main {
config.copy(colored = Some(mainInteractive)),
stdout, stderr, stdin,
stateCache,
env
env,
setIdle
)

if (mill.main.client.Util.isJava9OrAbove) {
Expand Down
6 changes: 4 additions & 2 deletions main/src/mill/main/MainRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class MainRunner(val config: ammonite.main.Cli.Config,
errPrintStream: PrintStream,
stdIn: InputStream,
stateCache0: Option[Evaluator.State] = None,
env : Map[String, String])
env : Map[String, String],
setIdle: Boolean => Unit)
extends ammonite.MainRunner(
config, outprintStream, errPrintStream,
stdIn, outprintStream, errPrintStream
Expand All @@ -35,8 +36,9 @@ class MainRunner(val config: ammonite.main.Cli.Config,
def statAll() = watched.forall{ case (file, lastMTime) =>
Interpreter.pathSignature(file) == lastMTime
}

setIdle(true)
while(statAll()) Thread.sleep(100)
setIdle(false)
}

/**
Expand Down
Loading

0 comments on commit a7cb99f

Please sign in to comment.