Skip to content

Commit

Permalink
Replace ipcsocket with junixsocket library (#1852)
Browse files Browse the repository at this point in the history
https://github.com/kohlschutter/junixsocket seems much more robust, especially for Windows.  
sbt-ipcsocket implements windows support via named pipes, which are similar to unix pipes.   
junixsocket uses named pipes directly on windows, since they are supported now in Win10 (from 2017).

https://kohlschutter.github.io/junixsocket/unixsockets.html
https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/

Fixes #1310

Pull request: #1852

Commits:

* Replace ipcsocket with junixsocket library
* fix docjar on windows
* revert javadocOptions change
* Fix copy-pasting hidden char..
* Bump
* Try hack around junixsocket CI issue
* Revert socket path
  • Loading branch information
sake92 authored May 2, 2022
1 parent ac15694 commit d3d866a
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 53 deletions.
10 changes: 3 additions & 7 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,8 @@ object Deps {

val flywayCore = ivy"org.flywaydb:flyway-core:8.0.2"
val graphvizJava = ivy"guru.nidi:graphviz-java:0.18.1"
// Warning: Avoid ipcsocket version 1.3.0, as it caused many failures on CI
val ipcsocket = ivy"org.scala-sbt.ipcsocket:ipcsocket:1.0.1"
val ipcsocketExcludingJna = ipcsocket.exclude(
"net.java.dev.jna" -> "jna",
"net.java.dev.jna" -> "jna-platform"
)
val junixsocket = ivy"com.kohlschutter.junixsocket:junixsocket-core:2.4.0"

object jetty {
val version = "8.2.0.v20160908"
val server = ivy"org.eclipse.jetty:jetty-server:${version}"
Expand Down Expand Up @@ -388,7 +384,7 @@ object main extends MillModule {

object client extends MillPublishModule {
override def ivyDeps = Agg(
Deps.ipcsocketExcludingJna
Deps.junixsocket
)
def generatedBuildInfo = T {
val dest = T.dest
Expand Down
16 changes: 6 additions & 10 deletions main/client/src/mill/main/client/MillClientMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import mill.main.client.lock.Locked;
import mill.main.client.lock.Locks;
import org.scalasbt.ipcsocket.UnixDomainSocket;
import org.scalasbt.ipcsocket.Win32NamedPipeSocket;
import org.newsclub.net.unix.AFUNIXSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;

import java.io.File;
import java.io.FileInputStream;
Expand Down Expand Up @@ -179,25 +179,21 @@ public static int 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;
Throwable socketThrowable = null;
long retryStart = System.currentTimeMillis();

while (ioSocket == null && System.currentTimeMillis() - retryStart < 5000) {
try {
String socketBaseName = "mill-" + Util.md5hex(new File(lockBase).getCanonicalPath());
ioSocket = Util.isWindows ?
new Win32NamedPipeSocket(Util.WIN32_PIPE_PREFIX + socketBaseName)
: new UnixDomainSocket(lockBase + "/" + socketBaseName + "-io");
String socketName = lockBase + "/mill-" + Util.md5hex(new File(lockBase).getCanonicalPath()) + "-io";
AFUNIXSocketAddress addr = AFUNIXSocketAddress.of(new File(socketName));
ioSocket = AFUNIXSocket.connectTo(addr);
} catch (Throwable e) {
socketThrowable = e;
Thread.sleep(1);
}
}

if (ioSocket == null) {
throw new Exception("Failed to connect to server", socketThrowable);
}
Expand Down
4 changes: 0 additions & 4 deletions main/client/src/mill/main/client/ProxyStreamPumper.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ public void run() {
lastData.poke();
}
} catch (IOException e) {
// when client pipe handle is closed, it throws an exception on read()...
if (Util.isWindows && e.getMessage().endsWith("233")) {
return; // ignore
}
e.printStackTrace();
System.exit(1);
}
Expand Down
6 changes: 0 additions & 6 deletions main/client/src/mill/main/client/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ public class Util {
public static boolean isJava9OrAbove = !System.getProperty("java.specification.version").startsWith("1.");
private static Charset utf8 = Charset.forName("UTF-8");

// Windows named pipe prefix (see https://github.com/sbt/ipcsocket/blob/v1.0.0/README.md)
// Win32NamedPipeServerSocket automatically adds this as a prefix (if it is not already is prefixed),
// but Win32NamedPipeSocket does not
// https://github.com/sbt/ipcsocket/blob/v1.0.0/src/main/java/org/scalasbt/ipcsocket/Win32NamedPipeServerSocket.java#L36
public static String WIN32_PIPE_PREFIX = "\\\\.\\pipe\\";

public static String[] parseArgs(InputStream argStream) throws IOException {
int argsLength = readInt(argStream);
String[] args = new String[argsLength];
Expand Down
34 changes: 8 additions & 26 deletions main/src/mill/main/MillServerMain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import sun.misc.{Signal, SignalHandler}
import java.io._
import java.net.Socket
import scala.jdk.CollectionConverters._
import org.scalasbt.ipcsocket._
import org.newsclub.net.unix.AFUNIXServerSocket
import org.newsclub.net.unix.AFUNIXSocketAddress
import mill.{BuildInfo, MillMain}
import mill.main.client._
import mill.api.DummyInputStream
Expand Down Expand Up @@ -95,22 +96,11 @@ class Server[T](
var running = true
while (running) {
Server.lockBlock(locks.serverLock) {
val socketBaseName = "mill-" + Util.md5hex(new File(lockBase).getCanonicalPath)
val (serverSocket, socketClose) =
if (Util.isWindows) {
val socketName = Util.WIN32_PIPE_PREFIX + socketBaseName
(
new Win32NamedPipeServerSocket(socketName),
() => new Win32NamedPipeSocket(socketName).close()
)
} else {
val socketName = lockBase + "/" + socketBaseName + "-io"
new File(socketName).delete()
(
new UnixDomainServerSocket(socketName),
() => new UnixDomainSocket(socketName).close()
)
}
val socketName = lockBase + "/mill-" + Util.md5hex(new File(lockBase).getCanonicalPath()) + "-io"
new File(socketName).delete()
val addr = AFUNIXSocketAddress.of(new File(socketName))
val serverSocket = AFUNIXServerSocket.bindOn(addr)
val socketClose = () => serverSocket.close()

val sockOpt = Server.interruptWith(
"MillSocketTimeoutInterruptThread",
Expand Down Expand Up @@ -225,15 +215,7 @@ class Server[T](
System.out.flush()
System.err.flush()

if (Util.isWindows) {
// Closing Win32NamedPipeSocket can often take ~5s
// It seems OK to exit the client early and subsequently
// start up mill client again (perhaps closing the server
// socket helps speed up the process).
val t = new Thread(() => clientSocket.close(), "clientSocketCloser")
t.setDaemon(true)
t.start()
} else clientSocket.close()
clientSocket.close()
}
}

Expand Down
6 changes: 6 additions & 0 deletions main/test/src/main/ClientServerTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class EchoServer extends MillServerMain[Int] {

object ClientServerTests extends TestSuite {

if (scala.util.Properties.isWin) {
// workaround for CI issue
// https://github.com/com-lihaoyi/mill/pull/1852#issuecomment-1114332274
System.setProperty("os.name", "Windows10")
}

val ENDL = System.lineSeparator()

def initStreams() = {
Expand Down

0 comments on commit d3d866a

Please sign in to comment.