BareGit

Fix potential FD ordering issue

Author: MetroWind <chris.corsair@gmail.com>
Date: Thu Sep 24 16:20:54 2026 -0700
Commit: d16bb9406d0b132b8e469b7dbf41379a87319891

Changes

diff --git a/src/engine_process.cpp b/src/engine_process.cpp
index 9578239..3b547f2 100644
--- a/src/engine_process.cpp
+++ b/src/engine_process.cpp
@@ -54,12 +54,13 @@ bool EngineProcess::start(const Json& start_message, EventCallback callback,
 
     posix_spawn_file_actions_t actions;
     posix_spawn_file_actions_init(&actions);
+    posix_spawn_file_actions_addclose(&actions, channel_fds[0]);
+    posix_spawn_file_actions_addclose(&actions, diagnostic_fds[0]);
     posix_spawn_file_actions_adddup2(&actions, channel_fds[1], 3);
     if(channel_fds[1] != 3)
     {
         posix_spawn_file_actions_addclose(&actions, channel_fds[1]);
     }
-    posix_spawn_file_actions_addclose(&actions, channel_fds[0]);
     posix_spawn_file_actions_adddup2(&actions, diagnostic_fds[1], STDOUT_FILENO);
     posix_spawn_file_actions_adddup2(&actions, diagnostic_fds[1], STDERR_FILENO);
     if(diagnostic_fds[1] != STDOUT_FILENO
@@ -67,7 +68,6 @@ bool EngineProcess::start(const Json& start_message, EventCallback callback,
     {
         posix_spawn_file_actions_addclose(&actions, diagnostic_fds[1]);
     }
-    posix_spawn_file_actions_addclose(&actions, diagnostic_fds[0]);
 
     std::string executable = executablePath();
     std::vector<char*> arguments;
@@ -169,17 +169,35 @@ void EngineProcess::readLoop()
 
     const pid_t process_id = process_id_;
     int status = 0;
+    pid_t waited = -1;
     if(process_id > 0)
     {
-        while(::waitpid(process_id, &status, 0) < 0 && errno == EINTR)
+        while((waited = ::waitpid(process_id, &status, 0)) < 0
+              && errno == EINTR)
         {
         }
     }
+    if(waited < 0)
+    {
+        std::fprintf(stderr, "NetHack worker %ld: waitpid failed: %s\n",
+                     static_cast<long>(process_id), std::strerror(errno));
+    }
+    else
+    {
+        std::fprintf(stderr,
+                     "NetHack worker %ld exited: code=%d signal=%d; %s\n",
+                     static_cast<long>(process_id),
+                     WIFEXITED(status) ? WEXITSTATUS(status) : -1,
+                     WIFSIGNALED(status) ? WTERMSIG(status) : 0,
+                     error.c_str());
+    }
     running_ = false;
     Json exiting = {
         {"type", "exiting"},
-        {"exit_code", WIFEXITED(status) ? WEXITSTATUS(status) : -1},
-        {"signal", WIFSIGNALED(status) ? WTERMSIG(status) : 0},
+        {"exit_code", waited > 0 && WIFEXITED(status)
+             ? WEXITSTATUS(status) : -1},
+        {"signal", waited > 0 && WIFSIGNALED(status)
+             ? WTERMSIG(status) : 0},
         {"error", error},
     };
     if(callback_)