upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-08-26 22:45:24 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-08-26 22:45:24 +0000
commit72242aadd602ee68c9a052386cfbd342b75a1977 (patch)
tree3caf6c71f52a1f45e6a5413922244283ad128bea /src
parent9b0535312a77a97b06837bbef51c1fe4b7f3b0da (diff)
tor: stop racing the watchdog for the managed-Tor pid
BtfStopManagedTor read, waited on and signalled g_managedTorPid without holding cs_managedTor, while the watchdog concurrently reaps the same child and resets it. If the watchdog won, the stop path spun ten seconds on ECHILD and then sent SIGKILL to a stale, potentially recycled pid. Snapshot the pid under the lock, treat ECHILD as already-exited, and only clear the global if it still holds our pid.
Diffstat (limited to 'src')
-rw-r--r--src/tor.cpp25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/tor.cpp b/src/tor.cpp
index 20b4577..fea6912 100644
--- a/src/tor.cpp
+++ b/src/tor.cpp
@@ -827,17 +827,26 @@ void BtfStopManagedTor()
827 memset(&g_managedTorProcess, 0, sizeof(g_managedTorProcess)); 827 memset(&g_managedTorProcess, 0, sizeof(g_managedTorProcess));
828 } 828 }
829#else 829#else
830 if (g_managedTorPid > 0) 830 // Snapshot the pid under the lock. The watchdog's ManagedTorProcessAlive
831 // reaps the same child concurrently and resets g_managedTorPid under
832 // cs_managedTor; reading the global unlocked here could leave us waiting
833 // on ECHILD and then SIGKILLing a recycled PID.
834 pid_t pid = -1;
835 CRITICAL_BLOCK(cs_managedTor)
836 pid = g_managedTorPid;
837 if (pid > 0)
831 { 838 {
832 std::string shutdownErr; 839 std::string shutdownErr;
833 if (!RequestManagedTorShutdown(shutdownErr)) 840 if (!RequestManagedTorShutdown(shutdownErr))
834 kill(g_managedTorPid, SIGTERM); 841 kill(pid, SIGTERM);
835 bool fExited = false; 842 bool fExited = false;
836 for (int i = 0; i < 100; i++) 843 for (int i = 0; i < 100; i++)
837 { 844 {
838 int status = 0; 845 int status = 0;
839 pid_t r = waitpid(g_managedTorPid, &status, WNOHANG); 846 pid_t r = waitpid(pid, &status, WNOHANG);
840 if (r == g_managedTorPid) 847 // ECHILD means the watchdog already reaped it -- that is exit,
848 // not a reason to signal anything.
849 if (r == pid || (r == -1 && errno == ECHILD))
841 { 850 {
842 fExited = true; 851 fExited = true;
843 break; 852 break;
@@ -846,10 +855,12 @@ void BtfStopManagedTor()
846 } 855 }
847 if (!fExited) 856 if (!fExited)
848 { 857 {
849 kill(g_managedTorPid, SIGKILL); 858 kill(pid, SIGKILL);
850 waitpid(g_managedTorPid, NULL, 0); 859 waitpid(pid, NULL, 0);
851 } 860 }
852 g_managedTorPid = -1; 861 CRITICAL_BLOCK(cs_managedTor)
862 if (g_managedTorPid == pid)
863 g_managedTorPid = -1;
853 } 864 }
854#endif 865#endif
855 CRITICAL_BLOCK(cs_managedTor) 866 CRITICAL_BLOCK(cs_managedTor)