aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2019-10-30 10:29:43 -0400
committerNick Mathewson <nickm@torproject.org>2019-11-07 07:28:43 -0500
commit52c0ab4af3ec152c4b78669acf8877ca27d66097 (patch)
treee8dc14ad0834731fd746bc22d462aae1db18ed3b
parent7ac4f9d5ec1b31a0d4b76ab62c1afc039c8fe627 (diff)
downloadtor-52c0ab4af3ec152c4b78669acf8877ca27d66097.tar.gz
tor-52c0ab4af3ec152c4b78669acf8877ca27d66097.zip
Add subsys functions for receiving/flushing states and options.
These functions are in the subsystem, not in the config_format_t, since they are about how the format is _used_, not about _what it is_.
-rw-r--r--src/app/config/config.c3
-rw-r--r--src/app/config/statefile.c4
-rw-r--r--src/app/main/subsysmgr.c76
-rw-r--r--src/app/main/subsysmgr.h8
-rw-r--r--src/lib/subsys/subsys.h29
5 files changed, 119 insertions, 1 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 7317a5d2f1..8929349709 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -987,7 +987,8 @@ set_options(or_options_t *new_val, char **msg)
global_options = old_options;
return -1;
}
- if (options_act(old_options) < 0) { /* acting on the options failed. die. */
+ if (subsystems_set_options(get_options_mgr(), new_val) < 0 ||
+ options_act(old_options) < 0) { /* acting on the options failed. die. */
if (! tor_event_loop_shutdown_is_pending()) {
log_err(LD_BUG,
"Acting on config options left us in a broken state. Dying.");
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index f6b0915da4..5fdb15ace1 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -316,6 +316,9 @@ or_state_set(or_state_t *new_state)
tor_assert(new_state);
config_free(get_state_mgr(), global_state);
global_state = new_state;
+ if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
+ ret = -1;
+ }
if (entry_guards_parse_state(global_state, 1, &err)<0) {
log_warn(LD_GENERAL,"%s",err);
tor_free(err);
@@ -519,6 +522,7 @@ or_state_save(time_t now)
/* Call everything else that might dirty the state even more, in order
* to avoid redundant writes. */
+ (void) subsystems_flush_state(get_state_mgr(), global_state);
entry_guards_update_state(global_state);
rep_hist_update_state(global_state);
circuit_build_times_update_state(get_circuit_build_times(), global_state);
diff --git a/src/app/main/subsysmgr.c b/src/app/main/subsysmgr.c
index e5c76b8e55..bd9af11444 100644
--- a/src/app/main/subsysmgr.c
+++ b/src/app/main/subsysmgr.c
@@ -334,3 +334,79 @@ subsystems_register_state_formats(config_mgr_t *mgr)
}
return 0;
}
+
+/**
+ * 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;
+}
diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h
index 54193f9649..7e5fe76362 100644
--- a/src/app/main/subsysmgr.h
+++ b/src/app/main/subsysmgr.h
@@ -34,5 +34,13 @@ void subsystems_thread_cleanup(void);
struct config_mgr_t;
int subsystems_register_options_formats(struct config_mgr_t *mgr);
int subsystems_register_state_formats(struct config_mgr_t *mgr);
+struct or_options_t;
+struct or_state_t;
+int subsystems_set_options(const struct config_mgr_t *mgr,
+ struct or_options_t *options);
+int subsystems_set_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
+int subsystems_flush_state(const struct config_mgr_t *mgr,
+ struct or_state_t *state);
#endif /* !defined(TOR_SUBSYSMGR_T) */
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 1cb3fe94a5..29a90c049d 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -101,6 +101,35 @@ typedef struct subsys_fns_t {
**/
const struct config_format_t *state_format;
+ /**
+ * Receive an options object as defined by options_format. Return 0
+ * on success, -1 on failure.
+ *
+ * It is safe to store the pointer to the object until set_options()
+ * is called again. */
+ int (*set_options)(void *);
+
+ /* XXXX Add an implementation for options_act_reversible() later in this
+ * branch. */
+
+ /**
+ * Receive a state object as defined by state_format. Return 0 on success,
+ * -1 on failure.
+ *
+ * It is safe to store the pointer to the object; set_state() is only
+ * called on startup.
+ **/
+ int (*set_state)(void *);
+
+ /**
+ * Update any information that needs to be stored in the provided state
+ * object (as defined by state_format). Return 0 on success, -1 on failure.
+ *
+ * The object provided here will be the same one as provided earlier to
+ * set_state(). This method is called when we are about to save the state
+ * to disk.
+ **/
+ int (*flush_state)(void *);
} subsys_fns_t;
/**