[tor-commits] [tor/master] torerr: Close sigsafe fds on shutdown

asn at torproject.org asn at torproject.org
Thu Sep 12 15:10:46 UTC 2019


commit d02ced4cafaed5b11079585f03f47e73034dd980
Author: teor <teor at torproject.org>
Date:   Wed Sep 4 14:54:08 2019 +1000

    torerr: Close sigsafe fds on shutdown
    
    And clear the list of error fds.
    
    Part of 31594.
---
 src/lib/err/torerr.c     | 42 ++++++++++++++++++++++++++++++++++++++++--
 src/lib/err/torerr.h     |  1 +
 src/lib/err/torerr_sys.c |  5 ++++-
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index ecffb7f7b..2c4a10a5b 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.
  */
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
index 0badaf7c6..3b86d2039 100644
--- a/src/lib/err/torerr.h
+++ b/src/lib/err/torerr.h
@@ -40,6 +40,7 @@ void tor_log_err_sigsafe(const char *m, ...);
 int tor_log_get_sigsafe_err_fds(const int **out);
 void tor_log_set_sigsafe_err_fds(const int *fds, int n);
 void tor_log_reset_sigsafe_err_fds(void);
+void tor_log_close_sigsafe_err_fds(void);
 void tor_log_sigsafe_err_set_granularity(int ms);
 
 int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c
index 3ab1b3c4e..a14c46f94 100644
--- a/src/lib/err/torerr_sys.c
+++ b/src/lib/err/torerr_sys.c
@@ -27,8 +27,11 @@ subsys_torerr_initialize(void)
 static void
 subsys_torerr_shutdown(void)
 {
-  tor_log_reset_sigsafe_err_fds();
+  /* Stop handling signals with backtraces, then close the logs. */
   clean_up_backtrace_handler();
+  /* We can't log any log messages after this point: we've closed all the log
+   * fds, including stdio. */
+  tor_log_close_sigsafe_err_fds();
 }
 
 const subsys_fns_t sys_torerr = {





More information about the tor-commits mailing list