|
@@ -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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -132,6 +144,32 @@ tor_log_reset_sigsafe_err_fds(void)
|
|
|
tor_log_set_sigsafe_err_fds(fds, 1);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 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.
|