From 36214040b59d187acf2cc1868f92c8d0093a6ec0 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Fri, 2 Dec 2022 10:21:00 +0100 Subject: [PATCH] Replicate failing to open port on Windows --- .github/workflows/ci.yml | 1 + main-command/src/main/scala/xsbt/IPC.scala | 9 ++++-- .../src/test/scala/xsbt/IPCSpec.scala | 30 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 main-command/src/test/scala/xsbt/IPCSpec.scala diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c2cc30a4f..8ca8753557 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -186,6 +186,7 @@ jobs: shell: bash run: | # test building sbtn on Windows + sbt "commandProj/testOnly xsbt.IPCSpec" sbt "-Dsbt.io.virtual=false" nativeImage # test launcher script echo build using JDK 8, test using JDK 8, on Windows diff --git a/main-command/src/main/scala/xsbt/IPC.scala b/main-command/src/main/scala/xsbt/IPC.scala index 9c353613dc..2bb33d8230 100644 --- a/main-command/src/main/scala/xsbt/IPC.scala +++ b/main-command/src/main/scala/xsbt/IPC.scala @@ -16,7 +16,7 @@ import scala.util.control.NonFatal object IPC { private val portMin = 1025 private val portMax = 65536 - private val loopback = InetAddress.getByName(null) + private[xsbt] val loopback = InetAddress.getByName(null) def client[T](port: Int)(f: IPC => T): T = ipc(new Socket(loopback, port))(f) @@ -34,7 +34,12 @@ object IPC { def createServer(attempts: Int): ServerSocket = if (attempts > 0) { - try new ServerSocket(nextPort, 1, loopback) + val backlog = + if (System.getProperty("os.name").toLowerCase.contains("win")) + 2 + else + 1 + try new ServerSocket(nextPort, backlog, loopback) catch { case NonFatal(_) => createServer(attempts - 1) } } else sys.error("Could not connect to socket: maximum attempts exceeded") diff --git a/main-command/src/test/scala/xsbt/IPCSpec.scala b/main-command/src/test/scala/xsbt/IPCSpec.scala new file mode 100644 index 0000000000..727c29eb15 --- /dev/null +++ b/main-command/src/test/scala/xsbt/IPCSpec.scala @@ -0,0 +1,30 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package xsbt + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers._ + +class IPCSpec extends AnyFlatSpec { + "server" should "find free open ports and close them" in { + noException should be thrownBy { + val server = IPC.unmanagedServer + (1 until 500).foreach { index => + try { + IPC.client(server.port)(identity) + } catch { + case e: Throwable => + val message = s"failure index is $index" + info(message) + throw e + } + } + server.close() + } + } +}