[tor-commits] [tor/master] Code to manage the list of subsystems.

nickm at torproject.org nickm at torproject.org
Fri Nov 9 20:01:54 UTC 2018


commit 7bb76b24cf755799b7950ef078ac5ccf4d6e3a8a
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Nov 1 11:51:33 2018 -0400

    Code to manage the list of subsystems.
---
 src/app/main/main.c           |   6 ++
 src/app/main/subsysmgr.c      | 130 ++++++++++++++++++++++++++++++++++++++++++
 src/app/main/subsysmgr.h      |  20 +++++++
 src/app/main/subsystem_list.c |  20 +++++++
 src/core/include.am           |   3 +
 src/lib/subsys/subsys.h       |   5 ++
 6 files changed, 184 insertions(+)

diff --git a/src/app/main/main.c b/src/app/main/main.c
index ae87add67..444d6ea7e 100644
--- a/src/app/main/main.c
+++ b/src/app/main/main.c
@@ -15,6 +15,7 @@
 #include "app/config/statefile.h"
 #include "app/main/main.h"
 #include "app/main/ntmain.h"
+#include "app/main/subsysmgr.h"
 #include "core/mainloop/connection.h"
 #include "core/mainloop/cpuworker.h"
 #include "core/mainloop/mainloop.h"
@@ -813,6 +814,9 @@ tor_free_all(int postfork)
     release_lockfile();
   }
   tor_libevent_free_all();
+
+  subsystems_shutdown();
+
   /* Stuff in util.c and address.c*/
   if (!postfork) {
     escaped(NULL);
@@ -1426,6 +1430,8 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
   event_set_mem_functions(tor_malloc_, tor_realloc_, tor_free_);
 #endif
 
+  subsystems_init();
+
   init_protocol_warning_severity_level();
 
   update_approx_time(time(NULL));
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
new file mode 100644
index 000000000..7974f2d23
--- /dev/null
+++ b/src/app/main/subsysmgr.c
@@ -0,0 +1,130 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "app/main/subsysmgr.h"
+#include "lib/err/torerr.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * True iff we have checked tor_subsystems for consistency.
+ **/
+static bool subsystem_array_validated = false;
+
+/**
+ * True if a given subsystem is initialized.  Expand this array if there
+ * are more than this number of subsystems.  (We'd rather not
+ * dynamically allocate in this module.)
+ **/
+static bool sys_initialized[128];
+
+/**
+ * Exit with a raw assertion if the subsystems list is inconsistent;
+ * initialize the subsystem_initialized array.
+ **/
+static void
+check_and_setup(void)
+{
+  if (subsystem_array_validated)
+    return;
+
+  raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
+  memset(sys_initialized, 0, sizeof(sys_initialized));
+
+  int last_level = MIN_SUBSYS_LEVEL;
+
+  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (sys->level < MIN_SUBSYS_LEVEL || sys->level > MAX_SUBSYS_LEVEL) {
+      fprintf(stderr, "BUG: Subsystem %s (at %u) has an invalid level %d. "
+              "It is supposed to be between %d and %d (inclusive).\n",
+              sys->name, i, sys->level, MIN_SUBSYS_LEVEL, MAX_SUBSYS_LEVEL);
+      raw_assert_unreached_msg("There is a bug in subsystem_list.c");
+    }
+    if (sys->level < last_level) {
+      fprintf(stderr, "BUG: Subsystem %s (at #%u) is in the wrong position. "
+              "Its level is %d; but the previous subsystem's level was %d.\n",
+              sys->name, i, sys->level, last_level);
+      raw_assert_unreached_msg("There is a bug in subsystem_list.c");
+    }
+    last_level = sys->level;
+  }
+
+  subsystem_array_validated = true;
+}
+
+/**
+ * Initialize all the subsystems; exit on failure.
+ **/
+int
+subsystems_init(void)
+{
+  return subsystems_init_upto(MAX_SUBSYS_LEVEL);
+}
+
+/**
+ * Initialize all the subsystems whose level is less than or equal to
+ * <b>target_level</b>; exit on failure.
+ **/
+int
+subsystems_init_upto(int target_level)
+{
+  check_and_setup();
+
+  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (!sys->supported)
+      continue;
+    if (sys->level > target_level)
+      break;
+    if (sys_initialized[i])
+      continue;
+    int r = 0;
+    if (sys->initialize)
+      r = sys->initialize();
+    if (r < 0) {
+      fprintf(stderr, "BUG: subsystem %s (at %u) initialization failed.\n",
+              sys->name, i);
+      raw_assert_unreached_msg("A subsystem couldn't be initialized.");
+    }
+    sys_initialized[i] = true;
+  }
+
+  return 0;
+}
+
+/**
+ * Shut down all the subsystems.
+ **/
+void
+subsystems_shutdown(void)
+{
+  subsystems_shutdown_downto(MIN_SUBSYS_LEVEL - 1);
+}
+
+/**
+ * Shut down all the subsystems whose level is above <b>target_level</b>.
+ **/
+void
+subsystems_shutdown_downto(int target_level)
+{
+  check_and_setup();
+
+  for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
+    const subsys_fns_t *sys = tor_subsystems[i];
+    if (!sys->supported)
+      continue;
+    if (sys->level <= target_level)
+      break;
+    if (! sys_initialized[i])
+      continue;
+    if (sys->shutdown)
+      sys->shutdown();
+    sys_initialized[i] = false;
+  }
+}
diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h
new file mode 100644
index 000000000..c9b892eee
--- /dev/null
+++ b/src/app/main/subsysmgr.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_SUBSYSMGR_T
+#define TOR_SUBSYSMGR_T
+
+#include "lib/subsys/subsys.h"
+
+extern const struct subsys_fns_t *tor_subsystems[];
+extern const unsigned n_tor_subsystems;
+
+int subsystems_init(void);
+int subsystems_init_upto(int level);
+
+void subsystems_shutdown(void);
+void subsystems_shutdown_downto(int level);
+
+#endif
diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c
new file mode 100644
index 000000000..fc1249e1c
--- /dev/null
+++ b/src/app/main/subsystem_list.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "app/main/subsysmgr.h"
+#include "lib/cc/compat_compiler.h"
+#include "lib/cc/torint.h"
+
+#include <stddef.h>
+
+/**
+ * Global list of the subsystems in Tor, in the order of their initialization.
+ **/
+const subsys_fns_t *tor_subsystems[] = {
+   NULL // placeholder.
+};
+
+const unsigned n_tor_subsystems = ARRAY_LENGTH(tor_subsystems);
diff --git a/src/core/include.am b/src/core/include.am
index 1b8ef2ac5..d3fce5428 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -11,6 +11,8 @@ LIBTOR_APP_A_SOURCES = 				\
 	src/app/config/confparse.c		\
 	src/app/config/statefile.c		\
 	src/app/main/main.c			\
+	src/app/main/subsystem_list.c		\
+	src/app/main/subsysmgr.c		\
 	src/core/crypto/hs_ntor.c		\
 	src/core/crypto/onion_crypto.c		\
 	src/core/crypto/onion_fast.c		\
@@ -191,6 +193,7 @@ noinst_HEADERS +=					\
 	src/app/config/statefile.h			\
 	src/app/main/main.h				\
 	src/app/main/ntmain.h				\
+	src/app/main/subsysmgr.h			\
 	src/core/crypto/hs_ntor.h			\
 	src/core/crypto/onion_crypto.h	        	\
 	src/core/crypto/onion_fast.h			\
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 7e4fe5363..012b218da 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -43,6 +43,8 @@ typedef struct subsys_fns_t {
    *
    * This function MUST NOT rely on any runtime configuration information;
    * it is only for global state or pre-configuration state.
+   *
+   * This function MUST NOT have any parts that can fail.
    **/
   int (*initialize)(void);
 
@@ -60,4 +62,7 @@ typedef struct subsys_fns_t {
 
 } subsys_fns_t;
 
+#define MIN_SUBSYS_LEVEL -100
+#define MAX_SUBSYS_LEVEL 100
+
 #endif





More information about the tor-commits mailing list