From 79f8514f3eb1b6fab32bf3d8c728d5cf2379d213 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Wed, 18 Mar 2026 20:28:55 -0600 Subject: [PATCH] Tighten reset cleanup --- .../petshop/backend/PortCleanupSupport.java | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/petshop/backend/PortCleanupSupport.java b/backend/src/main/java/com/petshop/backend/PortCleanupSupport.java index 939d5554..c6cb5d9b 100644 --- a/backend/src/main/java/com/petshop/backend/PortCleanupSupport.java +++ b/backend/src/main/java/com/petshop/backend/PortCleanupSupport.java @@ -5,6 +5,8 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.Locale; import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.IntFunction; import java.util.function.LongConsumer; import java.util.function.LongFunction; @@ -51,17 +53,17 @@ final class PortCleanupSupport { } private static Optional findListeningPid(int port) { - ProcessBuilder builder = new ProcessBuilder("sh", "-lc", "lsof -tiTCP:" + port + " -sTCP:LISTEN | head -n 1"); + ProcessBuilder builder = buildPortLookupCommand(port); builder.redirectErrorStream(true); try { Process process = builder.start(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - String line = reader.readLine(); + String line = firstNonBlankLine(reader); int exitCode = process.waitFor(); if (exitCode != 0 || line == null || line.isBlank()) { return Optional.empty(); } - return Optional.of(Long.parseLong(line.trim())); + return Optional.of(parsePid(line)); } } catch (IOException | InterruptedException | NumberFormatException ex) { if (ex instanceof InterruptedException) { @@ -80,10 +82,37 @@ final class PortCleanupSupport { ProcessHandle.of(pid).ifPresent(handle -> { handle.destroy(); try { - handle.onExit().get(); + handle.onExit().get(5, TimeUnit.SECONDS); + } catch (TimeoutException ex) { + handle.destroyForcibly(); } catch (Exception ex) { handle.destroyForcibly(); } }); } + + private static ProcessBuilder buildPortLookupCommand(int port) { + String os = System.getProperty("os.name", "").toLowerCase(Locale.ROOT); + if (os.contains("win")) { + return new ProcessBuilder("cmd", "/c", "netstat -ano -p tcp | findstr LISTENING | findstr :" + port); + } + return new ProcessBuilder("lsof", "-tiTCP:" + port, "-sTCP:LISTEN"); + } + + private static String firstNonBlankLine(BufferedReader reader) throws IOException { + String line; + while ((line = reader.readLine()) != null) { + if (!line.isBlank()) { + return line.trim(); + } + } + return null; + } + + private static long parsePid(String line) { + String trimmed = line.trim(); + int lastSpace = trimmed.lastIndexOf(' '); + String pidToken = lastSpace >= 0 ? trimmed.substring(lastSpace + 1) : trimmed; + return Long.parseLong(pidToken); + } }