Skip to content

Commit 2ed36ba

Browse files
Merge branch 'com-lihaoyi:main' into groovylib
2 parents 78123f1 + 2a3ad8d commit 2ed36ba

File tree

11 files changed

+64
-107
lines changed

11 files changed

+64
-107
lines changed

libs/daemon/client/src/mill/client/LaunchedServer.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
public abstract class LaunchedServer {
44
public abstract boolean isAlive();
55

6-
public abstract void kill();
7-
86
/// An operating system process was launched.
97
public static class OsProcess extends LaunchedServer {
108
public final ProcessHandle process;
@@ -22,13 +20,6 @@ public String toString() {
2220
public boolean isAlive() {
2321
return process.isAlive();
2422
}
25-
26-
@Override
27-
public void kill() {
28-
if (!process.destroy())
29-
throw new IllegalStateException(
30-
"Asked " + process + " to terminate, but the termination request failed.");
31-
}
3223
}
3324

3425
/// Code running in the same process.
@@ -50,10 +41,5 @@ public String toString() {
5041
public boolean isAlive() {
5142
return thread.isAlive();
5243
}
53-
54-
@Override
55-
public void kill() {
56-
_kill.run();
57-
}
5844
}
5945
}

libs/daemon/client/src/mill/client/ServerLauncher.java

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@
3737
/// - Wait for `ProxyStream.END` packet or `clientSocket.close()`,
3838
/// indicating server has finished execution and all data has been received
3939
public abstract class ServerLauncher {
40-
public static class RunWithConnectionResult<A> {
41-
public final A result;
42-
43-
public final int exitCode;
44-
45-
public RunWithConnectionResult(A result, int exitCode) {
46-
this.result = result;
47-
this.exitCode = exitCode;
48-
}
49-
}
5040

5141
/// Run a client logic with a connection established to a Mill server (via [#connectToServer]).
5242
///
@@ -56,13 +46,13 @@ public RunWithConnectionResult(A result, int exitCode) {
5646
// client logic
5747
/// @param runClientLogic the client logic to run
5848
/// @return the exit code that the server sent back
59-
public static <A> RunWithConnectionResult<A> runWithConnection(
60-
String debugName,
49+
public static int runWithConnection(
6150
Socket connection,
6251
Streams streams,
6352
boolean closeConnectionAfterClientLogic,
6453
Consumer<OutputStream> sendInitData,
65-
RunClientLogic<A> runClientLogic)
54+
Runnable runClientLogic,
55+
String debugName)
6656
throws Exception {
6757
// According to
6858
// https://pzemtsov.github.io/2015/01/19/on-the-benefits-of-stream-buffering-in-Java.html it
@@ -76,10 +66,10 @@ public static <A> RunWithConnectionResult<A> runWithConnection(
7666
socketOutputStream.flush();
7767
var pumperThread =
7868
startStreamPumpers(socketInputStream, socketOutputStream, streams, debugName);
79-
var result = runClientLogic.run();
69+
runClientLogic.run();
8070
if (closeConnectionAfterClientLogic) socketInputStream.close();
8171
pumperThread.join();
82-
return new RunWithConnectionResult<>(result, pumperThread.exitCode());
72+
return pumperThread.exitCode();
8373
}
8474

8575
/// Run a client logic with a connection established to a Mill server (via [#connectToServer]).
@@ -90,7 +80,6 @@ public static <A> RunWithConnectionResult<A> runWithConnection(
9080
/// @param runClientLogic the client logic to run
9181
/// @return the exit code that the server sent back
9282
public static <A> A runWithConnection(
93-
String debugName,
9483
Socket connection,
9584
boolean closeConnectionAfterClientLogic,
9685
Consumer<OutputStream> sendInitData,
@@ -266,11 +255,6 @@ public static ServerLaunchResult ensureServerIsRunning(
266255
public boolean isAlive() {
267256
throw new RuntimeException("not implemented, this should never happen");
268257
}
269-
270-
@Override
271-
public void kill() {
272-
throw new RuntimeException("not implemented, this should never happen");
273-
}
274258
};
275259
return Optional.of(new ServerLaunchResult.AlreadyRunning(launchedServer));
276260
} catch (IOException | NumberFormatException e) {
@@ -353,26 +337,11 @@ public interface InitServer {
353337
LaunchedServer init() throws Exception;
354338
}
355339

356-
public interface RunClientLogic<A> {
357-
/// Runs the client logic.
358-
A run() throws Exception;
359-
}
360-
361340
public interface RunClientLogicWithStreams<A> {
362341
/// Runs the client logic.
363342
A run(BufferedInputStream inStream, BufferedOutputStream outStream) throws Exception;
364343
}
365344

366-
public static class Result {
367-
public final int exitCode;
368-
public final Path daemonDir;
369-
370-
public Result(int exitCode, Path daemonDir) {
371-
this.exitCode = exitCode;
372-
this.daemonDir = daemonDir;
373-
}
374-
}
375-
376345
public static class Streams {
377346
/// The input stream to send to the server as the stdin.
378347
public final InputStream stdin;

libs/javalib/worker/src/mill/javalib/worker/JvmWorkerImpl.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,6 @@ class JvmWorkerImpl(args: JvmWorkerArgs) extends JvmWorkerApi with AutoCloseable
340340
val debugName =
341341
s"ZincWorker,TCP ${socket.getRemoteSocketAddress} -> ${socket.getLocalSocketAddress}"
342342
ServerLauncher.runWithConnection(
343-
debugName,
344343
socket,
345344
/* closeConnectionAfterCommand */ true,
346345
/* sendInitData */ _ => {},

libs/scalajslib/api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package mill.scalajslib.worker.api
33
import java.io.File
44
import java.nio.file.Path
55

6-
private[scalajslib] trait ScalaJSWorkerApi {
6+
private[scalajslib] trait ScalaJSWorkerApi extends AutoCloseable {
77
def link(
88
runClasspath: Seq[Path],
99
dest: File,

libs/scalajslib/package.mill

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object `package` extends MillStableScalaModule with BuildInfo {
4949
def scalajsWorkerVersion = crossValue
5050
def moduleDir: os.Path = super.moduleDir / scalajsWorkerVersion
5151
def compileModuleDeps =
52-
Seq(build.libs.scalajslib.api, build.core.constants, build.core.api.daemon)
52+
Seq(build.libs.scalajslib.api, build.libs.util, build.core.constants, build.core.api.daemon)
5353
def mandatoryMvnDeps = Seq.empty[Dep]
5454
def mvnDeps = Seq(Deps.scalafmtDynamic)
5555
def compileMvnDeps = super.mandatoryMvnDeps() ++ Seq(

libs/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ private[scalajslib] class ScalaJSWorker(jobs: Int)
2424
)
2525
val bridge = cl
2626
.loadClass("mill.scalajslib.worker.ScalaJSWorkerImpl")
27-
.getDeclaredConstructor()
28-
.newInstance()
27+
.getDeclaredConstructor(classOf[Int])
28+
.newInstance(jobs)
2929
.asInstanceOf[workerApi.ScalaJSWorkerApi]
3030

3131
(cl, bridge)
@@ -35,7 +35,9 @@ private[scalajslib] class ScalaJSWorker(jobs: Int)
3535
key: Seq[PathRef],
3636
value: (URLClassLoader, workerApi.ScalaJSWorkerApi)
3737
): Unit = {
38-
value._1.close()
38+
val (classloader, workerApi) = value
39+
workerApi.close()
40+
classloader.close()
3941
}
4042

4143
override def maxCacheSize: Int = jobs

libs/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package mill.scalajslib.worker
22

3-
import scala.concurrent.Await
4-
import scala.concurrent.duration.Duration
53
import java.io.File
64
import java.nio.file.Path
5+
import scala.concurrent.Await
6+
import scala.concurrent.duration.Duration
7+
8+
import com.armanbilge.sjsimportmap.ImportMappedIRFile
9+
import mill.constants.InputPumper
710
import mill.scalajslib.worker.api.*
811
import mill.scalajslib.worker.jsenv.*
12+
import mill.util.CachedFactory
913
import org.scalajs.ir.ScalaJSVersions
1014
import org.scalajs.linker.{PathIRContainer, PathOutputDirectory, PathOutputFile, StandardImpl}
1115
import org.scalajs.linker.interface.{
@@ -22,12 +26,7 @@ import org.scalajs.jsenv.{Input, JSEnv, RunConfig}
2226
import org.scalajs.testing.adapter.TestAdapter
2327
import org.scalajs.testing.adapter.TestAdapterInitializer as TAI
2428

25-
import scala.collection.mutable
26-
import scala.ref.SoftReference
27-
import com.armanbilge.sjsimportmap.ImportMappedIRFile
28-
import mill.constants.InputPumper
29-
30-
class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
29+
class ScalaJSWorkerImpl(jobs: Int) extends ScalaJSWorkerApi {
3130
private case class LinkerInput(
3231
isFullLinkJS: Boolean,
3332
optimizer: Boolean,
@@ -44,15 +43,12 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
4443
case s"1.$n.$_" if n.toIntOption.exists(_ < number) => false
4544
case _ => true
4645
}
47-
private object ScalaJSLinker {
46+
private object ScalaJSLinker extends CachedFactory[LinkerInput, (Linker, IRFileCache.Cache)] {
4847
private val irFileCache = StandardImpl.irFileCache()
49-
private val cache = mutable.Map.empty[LinkerInput, SoftReference[(Linker, IRFileCache.Cache)]]
50-
def reuseOrCreate(input: LinkerInput): (Linker, IRFileCache.Cache) = cache.get(input) match {
51-
case Some(SoftReference((linker, irFileCacheCache))) => (linker, irFileCacheCache)
52-
case _ =>
53-
val newResult = createLinker(input)
54-
cache.update(input, SoftReference(newResult))
55-
newResult
48+
override def maxCacheSize: Int = jobs
49+
override def setup(key: LinkerInput): (Linker, IRFileCache.Cache) = createLinker(key)
50+
override def teardown(key: LinkerInput, value: (Linker, IRFileCache.Cache)): Unit = {
51+
value._2.free()
5652
}
5753
private def createLinker(input: LinkerInput): (Linker, IRFileCache.Cache) = {
5854
val semantics = input.isFullLinkJS match {
@@ -197,23 +193,22 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
197193
minify: Boolean,
198194
importMap: Seq[ESModuleImportMapping],
199195
experimentalUseWebAssembly: Boolean
200-
): Either[String, Report] = {
196+
): Either[String, Report] = ScalaJSLinker.withValue(LinkerInput(
197+
isFullLinkJS = isFullLinkJS,
198+
optimizer = optimizer,
199+
sourceMap = sourceMap,
200+
moduleKind = moduleKind,
201+
esFeatures = esFeatures,
202+
moduleSplitStyle = moduleSplitStyle,
203+
outputPatterns = outputPatterns,
204+
minify = minify,
205+
dest = dest,
206+
experimentalUseWebAssembly = experimentalUseWebAssembly
207+
)) { (linker, irFileCacheCache) =>
201208
// On Scala.js 1.2- we want to use the legacy mode either way since
202209
// the new mode is not supported and in tests we always use legacy = false
203210
val useLegacy = forceOutJs || !minorIsGreaterThanOrEqual(3)
204211
import scala.concurrent.ExecutionContext.Implicits.global
205-
val (linker, irFileCacheCache) = ScalaJSLinker.reuseOrCreate(LinkerInput(
206-
isFullLinkJS = isFullLinkJS,
207-
optimizer = optimizer,
208-
sourceMap = sourceMap,
209-
moduleKind = moduleKind,
210-
esFeatures = esFeatures,
211-
moduleSplitStyle = moduleSplitStyle,
212-
outputPatterns = outputPatterns,
213-
minify = minify,
214-
dest = dest,
215-
experimentalUseWebAssembly = experimentalUseWebAssembly
216-
))
217212
val irContainersAndPathsFuture = PathIRContainer.fromClasspath(runClasspath)
218213
val testInitializer =
219214
if (testBridgeInit)
@@ -390,4 +385,6 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
390385
}
391386
Seq(input)
392387
}
388+
389+
override def close(): Unit = ScalaJSLinker.close()
393390
}

runner/client/src/mill/client/MillServerLauncher.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public MillServerLauncher(
4343
*/
4444
public abstract LaunchedServer initServer(Path daemonDir, Locks locks) throws Exception;
4545

46-
public Result run(Path daemonDir, String javaHome, Consumer<String> log) throws Exception {
46+
public int run(Path daemonDir, String javaHome, Consumer<String> log) throws Exception {
4747
Files.createDirectories(daemonDir);
4848

4949
var initData = new ClientInitData(
@@ -76,8 +76,6 @@ public Result run(Path daemonDir, String javaHome, Consumer<String> log) throws
7676
true /*openSocket*/)) {
7777
log.accept("runWithConnection: " + launched);
7878
var result = runWithConnection(
79-
"MillServerLauncher[" + launched.socket.getLocalSocketAddress() + " -> "
80-
+ launched.socket.getRemoteSocketAddress() + "]",
8179
launched.socket,
8280
streams,
8381
false,
@@ -93,19 +91,24 @@ public Result run(Path daemonDir, String javaHome, Consumer<String> log) throws
9391
() -> {
9492
log.accept("running client logic");
9593
forceTestFailure(daemonDir, log);
96-
return 0;
97-
});
98-
log.accept("runWithConnection exit code: " + result.exitCode);
99-
return new Result(result.exitCode, daemonDir);
94+
},
95+
"MillServerLauncher[" + launched.socket.getLocalSocketAddress() + " -> "
96+
+ launched.socket.getRemoteSocketAddress() + "]");
97+
log.accept("runWithConnection exit code: " + result);
98+
return result;
10099
}
101100
}
102101

103-
private void forceTestFailure(Path daemonDir, Consumer<String> log) throws Exception {
102+
private void forceTestFailure(Path daemonDir, Consumer<String> log) {
104103
if (forceFailureForTestingMillisDelay > 0) {
105104
log.accept(
106105
"Force failure for testing in " + forceFailureForTestingMillisDelay + "ms: " + daemonDir);
107-
Thread.sleep(forceFailureForTestingMillisDelay);
108-
throw new Exception("Force failure for testing: " + daemonDir);
106+
try {
107+
Thread.sleep(forceFailureForTestingMillisDelay);
108+
} catch (InterruptedException e) {
109+
throw new RuntimeException(e);
110+
}
111+
throw new RuntimeException("Force failure for testing: " + daemonDir);
109112
} else {
110113
log.accept("No force failure for testing: " + daemonDir);
111114
}

runner/launcher/src/mill/launcher/MillLauncherMain.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,9 @@ public static void main(String[] args) throws Exception {
4848
// Ensure that if we're running in BSP mode we don't start a daemon.
4949
//
5050
// This is needed because when Metals/Idea closes, they only kill the BSP client and the BSP
51-
// server lurks around
52-
// waiting for the next client to connect.
53-
//
51+
// server lurks around waiting for the next client to connect.
5452
// This is unintuitive from the user's perspective and wastes resources, as most people expect
55-
// everything related
56-
// to the BSP server to be killed when closing the editor.
53+
// everything related to the BSP server to be killed when closing the editor.
5754
if (bspMode) runNoDaemon = true;
5855

5956
var outMode = bspMode ? OutFolderMode.BSP : OutFolderMode.REGULAR;
@@ -116,12 +113,13 @@ public LaunchedServer initServer(Path daemonDir, Locks locks) throws Exception {
116113
}
117114
};
118115

119-
var daemonDir0 = Paths.get(outDir, OutFiles.millDaemon);
116+
var daemonDir = Paths.get(outDir, OutFiles.millDaemon);
120117
String javaHome = MillProcessLauncher.javaHome(outMode);
121118

122-
var exitCode = launcher.run(daemonDir0, javaHome, log).exitCode;
119+
MillProcessLauncher.prepareMillRunFolder(daemonDir);
120+
var exitCode = launcher.run(daemonDir, javaHome, log);
123121
if (exitCode == ClientUtil.ExitServerCodeWhenVersionMismatch()) {
124-
exitCode = launcher.run(daemonDir0, javaHome, log).exitCode;
122+
exitCode = launcher.run(daemonDir, javaHome, log);
125123
}
126124
System.exit(exitCode);
127125
} catch (Exception e) {

runner/launcher/src/mill/launcher/MillProcessLauncher.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ static int launchMillNoDaemon(
2626
final Path processDir =
2727
Paths.get(".").resolve(outFor(outMode)).resolve(millNoDaemon).resolve(sig);
2828

29+
MillProcessLauncher.prepareMillRunFolder(processDir);
30+
2931
final List<String> l = new ArrayList<>();
3032
l.addAll(millLaunchJvmCommand(outMode, runnerClasspath));
3133
Map<String, String> propsMap = ClientUtil.getUserSetProperties();
@@ -77,7 +79,7 @@ static Process configureRunMillProcess(ProcessBuilder builder, Path daemonDir) t
7779

7880
Path sandbox = daemonDir.resolve(DaemonFiles.sandbox);
7981
Files.createDirectories(sandbox);
80-
MillProcessLauncher.prepareMillRunFolder(daemonDir);
82+
8183
builder.environment().put(EnvVars.MILL_WORKSPACE_ROOT, new File("").getCanonicalPath());
8284
if (System.getenv(EnvVars.MILL_EXECUTABLE_PATH) == null)
8385
builder.environment().put(EnvVars.MILL_EXECUTABLE_PATH, getExecutablePath());

0 commit comments

Comments
 (0)