summaryrefslogtreecommitdiff
path: root/src/lib/err/torerr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/err/torerr.c')
-rw-r--r--src/lib/err/torerr.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index ecffb7f7bb..2c4a10a5bb 100644
--- a/src/lib/err/torerr.c
+++ b/src/lib/err/torerr.c
@@ -110,6 +110,8 @@ tor_log_get_sigsafe_err_fds(const int **out)
* Update the list of fds that get errors from inside a signal handler or
* other emergency condition. Ignore any beyond the first
* TOR_SIGSAFE_LOG_MAX_FDS.
+ *
+ * If fds is NULL or n is 0, clears the list of error fds.
*/
void
tor_log_set_sigsafe_err_fds(const int *fds, int n)
@@ -118,8 +120,18 @@ tor_log_set_sigsafe_err_fds(const int *fds, int n)
n = TOR_SIGSAFE_LOG_MAX_FDS;
}
- memcpy(sigsafe_log_fds, fds, n * sizeof(int));
- n_sigsafe_log_fds = n;
+ /* Clear the entire array. This code mitigates against some race conditions,
+ * but there are still some races here:
+ * - err logs are disabled while the array is cleared, and
+ * - a thread can read the old value of n_sigsafe_log_fds, then read a
+ * partially written array.
+ * We could fix these races using atomics, but atomics use the err module. */
+ n_sigsafe_log_fds = 0;
+ memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
+ if (fds && n > 0) {
+ memcpy(sigsafe_log_fds, fds, n * sizeof(int));
+ n_sigsafe_log_fds = n;
+ }
}
/**
@@ -133,6 +145,32 @@ tor_log_reset_sigsafe_err_fds(void)
}
/**
+ * Close the list of fds that get errors from inside a signal handler or
+ * other emergency condition. These fds are shared with the logging code:
+ * closing them flushes the log buffers, and prevents any further logging.
+ *
+ * This function closes stderr, so it should only be called immediately before
+ * process shutdown.
+ */
+void
+tor_log_close_sigsafe_err_fds(void)
+{
+ int n_fds, i;
+ const int *fds = NULL;
+
+ n_fds = tor_log_get_sigsafe_err_fds(&fds);
+ for (i = 0; i < n_fds; ++i) {
+ /* tor_log_close_sigsafe_err_fds_on_error() is called on error and on
+ * shutdown, so we can't log or take any useful action if close()
+ * fails. */
+ (void)close(fds[i]);
+ }
+
+ /* Don't even try logging, we've closed all the log fds. */
+ tor_log_set_sigsafe_err_fds(NULL, 0);
+}
+
+/**
* Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system.
*/