summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-30 23:00:16 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:17 -0300
commit1ab1d412e2768d9fe56a9e97ab60716a6d31063a (patch)
tree9bf7ab7193ee2c8fe333d67f1b4d90e9ffed98c7
parentc27222be8ba77a3a6bdda16978f3001510bde055 (diff)
downloadpardes-1ab1d412e2768d9fe56a9e97ab60716a6d31063a.tar.gz
pardes-1ab1d412e2768d9fe56a9e97ab60716a6d31063a.zip
A second pardes --detach=NAME while NAME runs says "a session named NAME is already running" and exits 1, with no error trace
The second session built its whole core before its bind failed, then returned an error that main printed with a Zig error-return trace. The name is now checked first: a live session's socket is said, and the process exits 1 having made nothing. Co-Authored-By: Claude Opus 5.5 <[email protected]>
-rw-r--r--src/detached/server.zig13
-rw-r--r--test/fs.py8
2 files changed, 20 insertions, 1 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig
index 78b85836..588912bb 100644
--- a/src/detached/server.zig
+++ b/src/detached/server.zig
@@ -1238,6 +1238,17 @@ pub const detached_cols = 160;
pub const detached_rows = 50;
pub fn run(init: std.process.Init, opts: pardes.Options, name: []const u8) !void {
+ // A name a live session holds: said, exit 1, before anything is made
+ // (no error trace, no second session racing the first for the socket).
+ if (comptime supported) {
+ var path_buf: [path_max]u8 = undefined;
+ if (sessionPath(&path_buf, name)) |path| if (ninep_io.statNoFollow(path) != null and alive(path)) {
+ var said: [path_max + 64]u8 = undefined;
+ const text = std.fmt.bufPrint(&said, "pardes: a session named {s} is already running\n", .{name}) catch "pardes: a session of that name is already running\n";
+ std.Io.File.stderr().writeStreamingAll(init.io, text) catch {};
+ std.process.exit(1);
+ };
+ }
const gpa = init.gpa;
const allocs = pardes.memory.init(gpa);
defer pardes.memory.deinit();
@@ -1282,7 +1293,7 @@ pub fn run(init: std.process.Init, opts: pardes.Options, name: []const u8) !void
try session.initAsync();
if (!session.listen(name)) {
try std.Io.File.stderr().writeStreamingAll(init.io, "pardes: could not bind a detached session socket\n");
- return error.NoSocket;
+ std.process.exit(1);
}
session.ninep = ninep_io.listen(init.io, gpa, core, opts.ninep_name, name, opts.ninep_tcp, opts.ninep_quic);
diff --git a/test/fs.py b/test/fs.py
index 2782407d..8d830c48 100644
--- a/test/fs.py
+++ b/test/fs.py
@@ -1306,6 +1306,14 @@ def test(binary, quic=False):
# opened is deleted, as an $EDITOR must; one on a file already open
# waits on that pane; a session that goes away ends it with 1.
with session(binary, root, 'wait') as (client, address):
+ # A second --detach of a name a live session holds: said, exit 1,
+ # no Zig error trace.
+ second_env = {k: v for k, v in os.environ.items() if not k.startswith('PARDES_')}
+ second_env.update(HOME=str(root), XDG_RUNTIME_DIR=str(root))
+ second = subprocess.run([binary, '--detach=wait'], cwd=root, env=second_env,
+ stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, timeout=20)
+ assert second.returncode == 1, second
+ assert second.stderr == b'pardes: a session named wait is already running\n', second.stderr
status = dict(line.split(maxsplit=1) for line in client.read('/status').decode().splitlines())
env = {k: v for k, v in os.environ.items() if k != 'PARDES_FORWARD_LOOK'}
env.update(PARDES_9P=str(address), PARDES_PANE='1', PARDES_PID=status['pid'])