diff options
Diffstat (limited to 'src/tor.cpp')
| -rw-r--r-- | src/tor.cpp | 25 |
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) |