diff options
author | Nick Mathewson <nickm@torproject.org> | 2019-11-07 08:59:42 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2019-11-07 08:59:42 -0500 |
commit | f6c9ca3a1d1c29a293915612e26cdbfeb050c192 (patch) | |
tree | b210ebcead649d0a22c6e09c11b726da15a01f7c /src/app/main/subsysmgr.c | |
parent | 582cee723a86e44f140a5057152df06659c36e71 (diff) | |
parent | de7053b8967db64ae2a871d11b12afbcb9b1f8a6 (diff) | |
download | tor-f6c9ca3a1d1c29a293915612e26cdbfeb050c192.tar.gz tor-f6c9ca3a1d1c29a293915612e26cdbfeb050c192.zip |
Merge branch 'config_subsys_v4'
Diffstat (limited to 'src/app/main/subsysmgr.c')
-rw-r--r-- | src/app/main/subsysmgr.c | 226 |
1 files changed, 215 insertions, 11 deletions
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c index 1f4bc840f2..8be4a7d75c 100644 --- a/src/app/main/subsysmgr.c +++ b/src/app/main/subsysmgr.c @@ -14,10 +14,12 @@ #include "orconfig.h" #include "app/main/subsysmgr.h" +#include "lib/confmgt/confmgt.h" #include "lib/dispatch/dispatch_naming.h" #include "lib/dispatch/msgtypes.h" #include "lib/err/torerr.h" #include "lib/log/log.h" +#include "lib/log/util_bug.h" #include "lib/malloc/malloc.h" #include "lib/pubsub/pubsub_build.h" #include "lib/pubsub/pubsub_connect.h" @@ -31,12 +33,42 @@ **/ static bool subsystem_array_validated = false; +/** Index value indicating that a subsystem has no options/state object, and + * so that object does not have an index. */ +#define IDX_NONE (-1) + +/** + * Runtime status of a single subsystem. + **/ +typedef struct subsys_status_t { + /** True if the given subsystem is initialized. */ + bool initialized; + /** Index for this subsystem's options object, or IDX_NONE for none. */ + int options_idx; + /** Index for this subsystem's state object, or IDX_NONE for none. */ + int state_idx; +} subsys_status_t; + +/** An overestimate of the number of subsystems. */ +#define N_SYS_STATUS 128 /** * 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]; +static subsys_status_t sys_status[N_SYS_STATUS]; + +/** Set <b>status</b> to a default (not set-up) state. */ +static void +subsys_status_clear(subsys_status_t *status) +{ + if (!status) + return; + memset(status, 0, sizeof(*status)); + status->initialized = false; + status->state_idx = IDX_NONE; + status->options_idx = IDX_NONE; +} /** * Exit with a raw assertion if the subsystems list is inconsistent; @@ -48,8 +80,8 @@ 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)); + raw_assert(ARRAY_LENGTH(sys_status) >= n_tor_subsystems); + memset(sys_status, 0, sizeof(sys_status)); int last_level = MIN_SUBSYS_LEVEL; @@ -67,6 +99,8 @@ check_and_setup(void) sys->name, i, sys->level, last_level); raw_assert_unreached_msg("There is a bug in subsystem_list.c"); } + subsys_status_clear(&sys_status[i]); + last_level = sys->level; } @@ -97,7 +131,7 @@ subsystems_init_upto(int target_level) continue; if (sys->level > target_level) break; - if (sys_initialized[i]) + if (sys_status[i].initialized) continue; int r = 0; if (sys->initialize) { @@ -112,7 +146,7 @@ subsystems_init_upto(int target_level) sys->name, i); raw_assert_unreached_msg("A subsystem couldn't be initialized."); } - sys_initialized[i] = true; + sys_status[i].initialized = true; } return 0; @@ -132,7 +166,7 @@ subsystems_add_pubsub_upto(pubsub_builder_t *builder, continue; if (sys->level > target_level) break; - if (! sys_initialized[i]) + if (! sys_status[i].initialized) continue; int r = 0; if (sys->add_pubsub) { @@ -186,13 +220,13 @@ subsystems_shutdown_downto(int target_level) continue; if (sys->level <= target_level) break; - if (! sys_initialized[i]) + if (! sys_status[i].initialized) continue; if (sys->shutdown) { log_debug(LD_GENERAL, "Shutting down %s", sys->name); sys->shutdown(); } - sys_initialized[i] = false; + subsys_status_clear(&sys_status[i]); } } @@ -208,7 +242,7 @@ subsystems_prefork(void) const subsys_fns_t *sys = tor_subsystems[i]; if (!sys->supported) continue; - if (! sys_initialized[i]) + if (! sys_status[i].initialized) continue; if (sys->prefork) { log_debug(LD_GENERAL, "Pre-fork: %s", sys->name); @@ -229,7 +263,7 @@ subsystems_postfork(void) const subsys_fns_t *sys = tor_subsystems[i]; if (!sys->supported) continue; - if (! sys_initialized[i]) + if (! sys_status[i].initialized) continue; if (sys->postfork) { log_debug(LD_GENERAL, "Post-fork: %s", sys->name); @@ -250,7 +284,7 @@ subsystems_thread_cleanup(void) const subsys_fns_t *sys = tor_subsystems[i]; if (!sys->supported) continue; - if (! sys_initialized[i]) + if (! sys_status[i].initialized) continue; if (sys->thread_cleanup) { log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name); @@ -258,3 +292,173 @@ subsystems_thread_cleanup(void) } } } + +/** + * Register all subsystem-declared options formats in <b>mgr</b>. + * + * Return 0 on success, -1 on failure. + **/ +int +subsystems_register_options_formats(config_mgr_t *mgr) +{ + tor_assert(mgr); + check_and_setup(); + + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + if (sys->options_format) { + int options_idx = config_mgr_add_format(mgr, sys->options_format); + sys_status[i].options_idx = options_idx; + log_debug(LD_CONFIG, "Added options format for %s with index %d", + sys->name, options_idx); + } + } + return 0; +} + +/** + * Register all subsystem-declared state formats in <b>mgr</b>. + * + * Return 0 on success, -1 on failure. + **/ +int +subsystems_register_state_formats(config_mgr_t *mgr) +{ + tor_assert(mgr); + check_and_setup(); + + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + if (sys->state_format) { + int state_idx = config_mgr_add_format(mgr, sys->state_format); + sys_status[i].state_idx = state_idx; + log_debug(LD_CONFIG, "Added state format for %s with index %d", + sys->name, state_idx); + } + } + return 0; +} + +#ifdef TOR_UNIT_TESTS +/** + * Helper: look up the index for <b>sys</b>. Return -1 if the subsystem + * is not recognized. + **/ +static int +subsys_get_idx(const subsys_fns_t *sys) +{ + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + if (sys == tor_subsystems[i]) + return (int)i; + } + return -1; +} + +/** + * Return the current state-manager's index for any state held by the + * subsystem <b>sys</b>. If <b>sys</b> has no options, return -1. + * + * Using raw indices can be error-prone: only do this from the unit + * tests. If you need a way to access another subsystem's configuration, + * that subsystem should provide access functions. + **/ +int +subsystems_get_options_idx(const subsys_fns_t *sys) +{ + int i = subsys_get_idx(sys); + tor_assert(i >= 0); + return sys_status[i].options_idx; +} + +/** + * Return the current state-manager's index for any state held by the + * subsystem <b>sys</b>. If <b>sys</b> has no state, return -1. + * + * Using raw indices can be error-prone: only do this from the unit + * tests. If you need a way to access another subsystem's state + * that subsystem should provide access functions. + **/ +int +subsystems_get_state_idx(const subsys_fns_t *sys) +{ + int i = subsys_get_idx(sys); + tor_assert(i >= 0); + return sys_status[i].state_idx; +} +#endif + +/** + * Call all appropriate set_options() methods to tell the various subsystems + * about a new set of torrc options. Return 0 on success, -1 on + * nonrecoverable failure. + **/ +int +subsystems_set_options(const config_mgr_t *mgr, struct or_options_t *options) +{ + /* XXXX This does not yet handle reversible option assignment; I'll + * do that later in this branch. */ + + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + if (sys_status[i].options_idx >= 0 && sys->set_options) { + void *obj = config_mgr_get_obj_mutable(mgr, options, + sys_status[i].options_idx); + int rv = sys->set_options(obj); + if (rv < 0) { + log_err(LD_CONFIG, "Error when handling option for %s; " + "cannot proceed.", sys->name); + return -1; + } + } + } + return 0; +} + +/** + * Call all appropriate set_state() methods to tell the various subsystems + * about an initial DataDir/state file. Return 0 on success, -1 on + * nonrecoverable failure. + **/ +int +subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state) +{ + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + if (sys_status[i].state_idx >= 0 && sys->set_state) { + void *obj = config_mgr_get_obj_mutable(mgr, state, + sys_status[i].state_idx); + int rv = sys->set_state(obj); + if (rv < 0) { + log_err(LD_CONFIG, "Error when handling state for %s; " + "cannot proceed.", sys->name); + return -1; + } + } + } + return 0; +} + +/** + * Call all appropriate flush_state() methods to tell the various subsystems + * to update the state objects in <b>state</b>. Return 0 on success, + * -1 on failure. + **/ +int +subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state) +{ + int result = 0; + for (unsigned i = 0; i < n_tor_subsystems; ++i) { + const subsys_fns_t *sys = tor_subsystems[i]; + if (sys_status[i].state_idx >= 0 && sys->flush_state) { + void *obj = config_mgr_get_obj_mutable(mgr, state, + sys_status[i].state_idx); + int rv = sys->flush_state(obj); + if (rv < 0) { + log_warn(LD_CONFIG, "Error when flushing state to state object for %s", + sys->name); + result = -1; + } + } + } + return result; +} |