From 939a27005b2dd4ac1556e104fc91122f3aea0a6c Mon Sep 17 00:00:00 2001 From: Oliver Davies Date: Sun, 23 Aug 2026 22:04:43 +0100 Subject: [PATCH] Clear a port held by more than one process `clear-port` killed nothing whenever more than one process held the port: kill: `453236 785863': not a pid or valid job spec lsof prints one PID per line, and quoting the result handed the whole list to kill as a single argument. Pipe the PIDs into xargs so that each becomes an argument of its own, which also retires the `$?` check that only ever guarded the empty case. Batching them into one kill matters as much as unquoting. A forked server shares its listening socket with every worker, so the parent and the workers all appear in the LISTEN list, and the parent tears its workers down as soon as it is signalled. Signalling one PID at a time would reach those workers after they had already gone and report `No such process` for a run that did exactly what it set out to do. A single kill sends every signal without waiting for the parent to reap them in between. More than one process is the ordinary case rather than an edge case, because `lsof -ti4TCP:PORT` matches established connections as well as listeners, so a browser with the page open is listed alongside the server it is talking to. `-sTCP:LISTEN` narrows the match to the listening process, which is both what the script sets out to kill and what stops the browser being killed once kill starts working. The pipe into xargs is preferred to an unquoted `$(...)`, which batches just as well but trips SC2086 and runs kill with no arguments when the port is free. `-r` covers that last case on GNU xargs, and is a documented no-op on the BSD xargs that ships with macOS. --- bin/clear-port | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/clear-port b/bin/clear-port index bc3f4d064e..993c1e2c91 100755 --- a/bin/clear-port +++ b/bin/clear-port @@ -1,14 +1,13 @@ #!/bin/sh -# Kills the process running on the provided port +# Kills the processes listening on the provided port # # clear-port 3000 if [ -n "$1" ]; then - port_num="$(lsof -ti4TCP:"$1")" - if [ $? -eq 0 ]; then - kill "$port_num" - fi + # A port can be held by more than one process, and a forked server's workers + # die with the parent, so signal every PID in a single kill. + lsof -ti4TCP:"$1" -sTCP:LISTEN | xargs -r kill else echo >&2 Usage: clear-port port-number exit 1