From 7f1a7e5a50695a2b48e161b528caa9f995ec9d0d Mon Sep 17 00:00:00 2001 From: Godopu Date: Thu, 16 Jul 2026 23:20:59 +0900 Subject: [PATCH] fix(ui): enforce async-signal-safe exit, blocking waitpid reaping, and unsetenv env isolation inside child PTY process --- .../test/incremental_kernel.Ly9AZGFydD0zLjA= | Bin 4058736 -> 4060680 bytes .../packages/mam_pty/lib/src/pty_session.dart | 42 +++++++++++++----- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/.dart_tool/test/incremental_kernel.Ly9AZGFydD0zLjA= index e6f48d0a5be710dd4762e2617bca76c45f63ea6b..f600b09759587c1bb55d7546a87b9e19e7ef4f59 100644 GIT binary patch delta 17779 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 H!^r;w7KuQJ delta 15965 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 DjwMSr diff --git a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/lib/src/pty_session.dart b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/lib/src/pty_session.dart index a5fbdfc..0b00bb1 100644 --- a/.agents/skills/multi-agent-mux-ui/packages/mam_pty/lib/src/pty_session.dart +++ b/.agents/skills/multi-agent-mux-ui/packages/mam_pty/lib/src/pty_session.dart @@ -53,6 +53,12 @@ typedef _chdir_dart = int Function(ffi.Pointer path); typedef _fcntl_c = ffi.Int32 Function(ffi.Int32 fd, ffi.Int32 cmd, ffi.Int32 arg); typedef _fcntl_dart = int Function(int fd, int cmd, int arg); +typedef _unsetenv_c = ffi.Int32 Function(ffi.Pointer name); +typedef _unsetenv_dart = int Function(ffi.Pointer name); + +typedef _exit_c = ffi.Void Function(ffi.Int32 status); +typedef _exit_dart = void Function(int status); + base class Winsize extends ffi.Struct { @ffi.Uint16() external int ws_row; @@ -101,6 +107,8 @@ class PtySession { final ioctl = libc.lookupFunction<_ioctl_c, _ioctl_dart>('ioctl'); final chdir = libc.lookupFunction<_chdir_c, _chdir_dart>('chdir'); final fcntl = libc.lookupFunction<_fcntl_c, _fcntl_dart>('fcntl'); + final unsetenv = libc.lookupFunction<_unsetenv_c, _unsetenv_dart>('unsetenv'); + final cExit = libc.lookupFunction<_exit_c, _exit_dart>('exit'); // 1. Prepare master PTY final masterFd = posixOpenpt(2 | 0x00000400); @@ -132,16 +140,15 @@ class PtySession { fcntl(masterFd, 4, flags | 2048); } - // 2. Resolve environment, isolating nested TMUX contexts (§6.7) - final env = Map.from(environment ?? Platform.environment); - env.remove('TMUX'); - env.remove('TMUX_PANE'); - - // 3. Pre-allocate ALL structures on the heap before fork() for async-signal-safety (§6.7) + // 2. Pre-allocate ALL structures on the heap before fork() for async-signal-safety (§6.7) final pathPtr = slaveName.toNativeUtf8(); final exePtr = executable.toNativeUtf8(); final workDirPtr = workingDirectory?.toNativeUtf8(); + // Environment isolation variables to be cleared in child context + final tmuxNamePtr = 'TMUX'.toNativeUtf8(); + final tmuxPaneNamePtr = 'TMUX_PANE'.toNativeUtf8(); + final argsCount = arguments.length; final argv = malloc>(argsCount + 2); argv[0] = exePtr.cast(); @@ -154,12 +161,14 @@ class PtySession { } argv[argsCount + 1] = ffi.Pointer.fromAddress(0); - // 4. Fork child process + // 3. Fork child process final pid = fork(); if (pid < 0) { close(masterFd); malloc.free(pathPtr); malloc.free(exePtr); + malloc.free(tmuxNamePtr); + malloc.free(tmuxPaneNamePtr); if (workDirPtr != null) malloc.free(workDirPtr); malloc.free(argv); for (final p in allocatedArgs) { @@ -169,12 +178,18 @@ class PtySession { } if (pid == 0) { - // --- CHILD PROCESS BRANCH (Strictly async-signal-safe syscalls only!) --- + // --- CHILD PROCESS BRANCH (Strictly async-signal-safe OS calls only!) --- + // A. Disassociate controlling terminal setsid(); + // B. Isolate from nested TMUX environments (§6.7) + unsetenv(tmuxNamePtr.cast()); + unsetenv(tmuxPaneNamePtr.cast()); + + // C. Open slave and redirect stdio final slaveFd = open(pathPtr.cast(), 2); if (slaveFd < 0) { - exit(-1); + cExit(-1); // direct libc _exit to prevent async-signal-unsafe Dart runtime exit } ioctl(slaveFd, 0x540E, ffi.Pointer.fromAddress(0)); @@ -193,12 +208,14 @@ class PtySession { } execvp(exePtr.cast(), argv); - exit(-2); + cExit(-2); // direct libc _exit on exec failure } // --- PARENT PROCESS BRANCH --- malloc.free(pathPtr); malloc.free(exePtr); + malloc.free(tmuxNamePtr); + malloc.free(tmuxPaneNamePtr); if (workDirPtr != null) malloc.free(workDirPtr); malloc.free(argv); for (final p in allocatedArgs) { @@ -279,16 +296,17 @@ class PtySession { final close = libc.lookupFunction<_close_c, _close_dart>('close'); close(masterFd); + // Send SIGTERM to terminate child process final kill = libc.lookupFunction< ffi.Int32 Function(ffi.Int32 pid, ffi.Int32 sig), int Function(int pid, int sig) >('kill'); kill(childPid, 15); // SIGTERM = 15 - // Reap child zombie process (non-blocking WNOHANG = 1) + // Reap child zombie process (blocking waitpid options = 0 to guarantee reaping) final waitpid = libc.lookupFunction<_waitpid_c, _waitpid_dart>('waitpid'); final statusPtr = calloc(); - waitpid(childPid, statusPtr, 1); + waitpid(childPid, statusPtr, 0); // Blocking wait guarantees process resource removal calloc.free(statusPtr); } }