mirror of https://github.com/sbt/sbt.git
Use jni implementation of ipcsocket apis on arm macs
There isn't yet a version of the jna available that works with the new apple silicon using arm64. To workaround this, we can use the jni implementation by default on arm64 macs. If the user wants to force the jni implementation for any supported platform, they can opt in with the `sbt.ipcsocket.jni` system property and/or by setting the serverUseJni setting.
This commit is contained in:
parent
8e7e3efea1
commit
ab2875e837
|
|
@ -31,7 +31,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import net.openhft.hashing.LongHashFunction;
|
||||
import org.scalasbt.ipcsocket.UnixDomainServerSocket;
|
||||
import org.scalasbt.ipcsocket.UnixDomainSocket;
|
||||
import org.scalasbt.ipcsocket.Win32NamedPipeServerSocket;
|
||||
import org.scalasbt.ipcsocket.Win32NamedPipeSocket;
|
||||
import org.scalasbt.ipcsocket.Win32SecurityLevel;
|
||||
|
|
@ -337,18 +336,24 @@ public class BootServerSocket implements AutoCloseable {
|
|||
static ServerSocket newSocket(final String sock) throws ServerAlreadyBootingException {
|
||||
ServerSocket socket = null;
|
||||
String name = socketName(sock);
|
||||
boolean jni = requiresJNI() || System.getProperty("sbt.ipcsocket.jni", "false").equals("true");
|
||||
try {
|
||||
if (!isWindows) Files.deleteIfExists(Paths.get(sock));
|
||||
socket =
|
||||
isWindows
|
||||
? new Win32NamedPipeServerSocket(name, false, Win32SecurityLevel.OWNER_DACL)
|
||||
: new UnixDomainServerSocket(name);
|
||||
? new Win32NamedPipeServerSocket(name, jni, Win32SecurityLevel.OWNER_DACL)
|
||||
: new UnixDomainServerSocket(name, jni);
|
||||
return socket;
|
||||
} catch (final IOException e) {
|
||||
throw new ServerAlreadyBootingException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean requiresJNI() {
|
||||
final boolean isMac = System.getProperty("os.name").toLowerCase().startsWith("mac");
|
||||
return isMac && !System.getProperty("os.arch", "").equals("x86_64");
|
||||
}
|
||||
|
||||
private static String socketName(String sock) {
|
||||
return isWindows ? "\\\\.\\pipe\\" + sock : sock;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ object BasicKeys {
|
|||
"Configures the security level of the named pipe. Values: 0 - No security; 1 - Logon user only; 2 - Process owner only",
|
||||
10000
|
||||
)
|
||||
val serverUseJni =
|
||||
AttributeKey[Boolean](
|
||||
"serverUseJni",
|
||||
"Toggles whether to use the jna or jni implementation in ipcsocket.",
|
||||
10000
|
||||
)
|
||||
|
||||
val serverIdleTimeout =
|
||||
AttributeKey[Option[FiniteDuration]](
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ private[sbt] object Server {
|
|||
addServerError(
|
||||
new Win32NamedPipeServerSocket(
|
||||
pipeName,
|
||||
false,
|
||||
connection.useJni,
|
||||
connection.windowsServerSecurityLevel
|
||||
)
|
||||
)
|
||||
|
|
@ -80,9 +80,9 @@ private[sbt] object Server {
|
|||
"or define a short \"SBT_GLOBAL_SERVER_DIR\" value. " +
|
||||
s"Current path: ${path}"
|
||||
)
|
||||
tryClient(new UnixDomainSocket(path))
|
||||
tryClient(new UnixDomainSocket(path, connection.useJni))
|
||||
prepareSocketfile()
|
||||
addServerError(new UnixDomainServerSocket(path))
|
||||
addServerError(new UnixDomainServerSocket(path, connection.useJni))
|
||||
case ConnectionType.Tcp =>
|
||||
tryClient(new Socket(InetAddress.getByName(host), port))
|
||||
addServerError(new ServerSocket(port, 50, InetAddress.getByName(host)))
|
||||
|
|
@ -238,7 +238,8 @@ private[sbt] case class ServerConnection(
|
|||
socketfile: File,
|
||||
pipeName: String,
|
||||
appConfiguration: AppConfiguration,
|
||||
windowsServerSecurityLevel: Int
|
||||
windowsServerSecurityLevel: Int,
|
||||
useJni: Boolean,
|
||||
) {
|
||||
def shortName: String = {
|
||||
connectionType match {
|
||||
|
|
|
|||
|
|
@ -383,6 +383,7 @@ object Defaults extends BuildCommon {
|
|||
},
|
||||
serverHandlers :== Nil,
|
||||
windowsServerSecurityLevel := Win32SecurityLevel.OWNER_DACL, // allows any owner logon session to access the server
|
||||
serverUseJni := BootServerSocket.requiresJNI || SysProp.serverUseJni,
|
||||
fullServerHandlers := Nil,
|
||||
insideCI :== sys.env.contains("BUILD_NUMBER") ||
|
||||
sys.env.contains("CI") || SysProp.ci,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ object Keys {
|
|||
val serverConnectionType = SettingKey(BasicKeys.serverConnectionType)
|
||||
val serverIdleTimeout = SettingKey(BasicKeys.serverIdleTimeout)
|
||||
val windowsServerSecurityLevel = SettingKey(BasicKeys.windowsServerSecurityLevel)
|
||||
val serverUseJni = SettingKey(BasicKeys.serverUseJni)
|
||||
val fullServerHandlers = SettingKey(BasicKeys.fullServerHandlers)
|
||||
val serverHandlers = settingKey[Seq[ServerHandler]]("User-defined server handlers.")
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ private[sbt] object xMain {
|
|||
case _: ServerAlreadyBootingException =>
|
||||
if (SysProp.forceServerStart) (None, None)
|
||||
else (None, Some(Exit(2)))
|
||||
case _: UnsatisfiedLinkError => (None, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import Keys.{
|
|||
serverIdleTimeout,
|
||||
serverLog,
|
||||
serverPort,
|
||||
serverUseJni,
|
||||
serverAuthentication,
|
||||
serverConnectionType,
|
||||
fullServerHandlers,
|
||||
|
|
@ -529,10 +530,12 @@ object Project extends ProjectExtra {
|
|||
projectCommand
|
||||
)
|
||||
val winSecurityLevel = get(windowsServerSecurityLevel).getOrElse(2)
|
||||
val useJni = get(serverUseJni).getOrElse(false)
|
||||
val newAttrs =
|
||||
s.attributes
|
||||
.put(historyPath.key, history)
|
||||
.put(windowsServerSecurityLevel.key, winSecurityLevel)
|
||||
.put(serverUseJni.key, useJni)
|
||||
.setCond(autoStartServer.key, startSvr)
|
||||
.setCond(serverPort.key, port)
|
||||
.setCond(serverHost.key, host)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ private[sbt] final class CommandExchange {
|
|||
lazy val connectionType = s.get(serverConnectionType).getOrElse(ConnectionType.Tcp)
|
||||
lazy val handlers = s.get(fullServerHandlers).getOrElse(Nil)
|
||||
lazy val win32Level = s.get(windowsServerSecurityLevel).getOrElse(2)
|
||||
lazy val useJni = s.get(serverUseJni).getOrElse(false)
|
||||
lazy val portfile = s.baseDir / "project" / "target" / "active.json"
|
||||
|
||||
def onIncomingSocket(socket: Socket, instance: ServerInstance): Unit = {
|
||||
|
|
@ -223,6 +224,7 @@ private[sbt] final class CommandExchange {
|
|||
pipeName,
|
||||
s.configuration,
|
||||
win32Level,
|
||||
useJni,
|
||||
)
|
||||
val serverInstance = Server.start(connection, onIncomingSocket, s.log)
|
||||
// don't throw exception when it times out
|
||||
|
|
|
|||
|
|
@ -178,6 +178,8 @@ object SysProp {
|
|||
}
|
||||
}
|
||||
|
||||
def serverUseJni = getOrFalse("sbt.ipcsocket.jni")
|
||||
|
||||
private[this] def file(value: String): File = new File(value)
|
||||
private[this] def home: File = file(sys.props("user.home"))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue