[tor-commits] [tor/master] Improve subsys documentation; add initialization documentation.

nickm at torproject.org nickm at torproject.org
Fri Nov 15 14:10:31 UTC 2019


commit a6d22d7fc2c5f5c868fda4ed1224216a16c25f84
Author: Nick Mathewson <nickm at torproject.org>
Date:   Sun Nov 10 16:11:40 2019 -0500

    Improve subsys documentation; add initialization documentation.
---
 src/lib/subsys/initialization.dox | 76 +++++++++++++++++++++++++++++++++++++++
 src/lib/subsys/subsys.h           | 58 ++++++++++++++++++++++++++++--
 src/mainpage.dox                  |  3 ++
 3 files changed, 135 insertions(+), 2 deletions(-)

diff --git a/src/lib/subsys/initialization.dox b/src/lib/subsys/initialization.dox
new file mode 100644
index 000000000..3b500f962
--- /dev/null
+++ b/src/lib/subsys/initialization.dox
@@ -0,0 +1,76 @@
+/**
+
+ at page initialization Initialization and shutdown
+
+ at tableofcontents
+
+ at section overview Overview
+
+Tor has a single entry point: tor_run_main() in main.c.  All the ways of
+starting a Tor process (ntmain.c, tor_main.c, and tor_api.c) work by invoking tor_run_main().
+
+The tor_run_main() function normally exits (\ref init_exceptwhen "1") by
+returning: not by calling abort() or exit().  Before it returns, it calls
+tor_cleanup() in shutdown.c.
+
+Conceptually, there are several stages in running Tor.
+
+1. First, we initialize those modules that do not depend on the
+   configuration.  This happens in the first half of tor_run_main(), and the
+   first half of tor_init().  (\ref init_pending_refactor "2")
+
+2. Second, we parse the command line and our configuration, and configure
+   systems that depend on our configuration or state.  This configuration
+   happens midway through tor_init(), which invokes
+   options_init_from_torrc().  We then initialize more systems from the
+   second half of tor_init().
+
+3. At this point we may exit early if we have been asked to do something
+   requiring no further initialization, like printing our version number or
+   creating a new signing key.  Otherwise, we proceed to run_tor_main_loop(),
+   which initializes some network-specific parts of Tor, grabs some
+   daemon-only resources (like the data directory lock) and starts Tor itself
+   running.
+
+
+> \anchor init_exceptwhen 1. tor_run_main() _can_ terminate with a call to
+> abort() or exit(), but only when crashing due to a bug, or when forking to
+> run as a daemon.
+
+> \anchor init_pending_refactor 2. The pieces of code that I'm describing as
+> "the first part of tor_init()" and so on deserve to be functions with their
+> own name.  I'd like to refactor them, but before I do so, there is some
+> slight reorganization that needs to happen.  Notably, the
+> nt_service_parse_options() call ought logically to be later in our
+> initialization sequence.  See \ticket{32447} for our refactoring progress.
+
+
+ at section subsys Subsystems and initialization
+
+Our current convention is to use the subsystem mechanism to initialize and
+clean up pieces of Tor.  The more recently updated pieces of Tor will use
+this mechanism.  For examples, see e.g. time_sys.c or log_sys.c.
+
+In simplest terms, a **subsytem** is a logically separate part of Tor that
+can be initialized, shut down, managed, and configured somewhat independently
+of the rest of the program.
+
+To define a subsystem, we declare a `static const` instance of subsys_fns_t,
+describing the subsystem and a set of functions that initialize it,
+deconstruct it, and so on.  See the documentation for subsys_fns_t for a full
+list of these functions.
+
+After defining a subsytem, it must be inserted in subsystem_list.c.  At that
+point, table-driven mechanisms in subsysmgr.c will invoke its functions when
+appropriate.
+
+ at subsection vsconfig Initialization versus configuration
+
+We note that the initialization phase of Tor occurs before any configuration
+is read from disk -- and therefore before any other files are read from
+disk.  Therefore, any behavior that depends on Tor's configuration or state
+must occur _after_ the initialization process, during configuration.
+
+
+
+**/
diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h
index 29a90c049..258d060bb 100644
--- a/src/lib/subsys/subsys.h
+++ b/src/lib/subsys/subsys.h
@@ -25,6 +25,13 @@ struct config_format_t;
  *
  * You should use c99 named-field initializers with this structure: we
  * will be adding more fields, often in the middle of the structure.
+ *
+ * See \ref initialization for more information about initialization and
+ * shutdown in Tor.
+ *
+ * To make a new subsystem, you declare a const instance of this type, and
+ * include it on the list in subsystem_list.c.  The code that manages these
+ * subsystems is in subsysmgr.c.
  **/
 typedef struct subsys_fns_t {
   /**
@@ -55,7 +62,7 @@ typedef struct subsys_fns_t {
    * it is only for global state or pre-configuration state.
    *
    * (If you need to do any setup that depends on configuration, you'll need
-   * to declare a configuration callback. (Not yet designed))
+   * to declare a configuration callback instead. (Not yet designed))
    *
    * This function MUST NOT have any parts that can fail.
    **/
@@ -63,22 +70,49 @@ typedef struct subsys_fns_t {
 
   /**
    * Connect a subsystem to the message dispatch system.
+   *
+   * This function should use the macros in \refdir{lib/pubsub} to register a
+   * set of messages that this subsystem may publish, and may subscribe to.
+   *
+   * See pubsub_macros.h for more information, and for examples.
    **/
   int (*add_pubsub)(struct pubsub_connector_t *);
 
   /**
    * Perform any necessary pre-fork cleanup.  This function may not fail.
+   *
+   * On Windows (and any other platforms without fork()), this function will
+   * never be invoked.  Otherwise it is used when we are about to start
+   * running as a background daemon, or when we are about to run a unit test
+   * in a subprocess.  Unlike the subsys_fns_t.postfork callback, it is run
+   * from the parent process.
+   *
+   * Note that we do not invoke this function when the child process's only
+   * purpose is to call exec() and run another program.
    */
   void (*prefork)(void);
 
   /**
    * Perform any necessary post-fork setup. This function may not fail.
+   *
+   * On Windows (and any other platforms without fork()), this function will
+   * never be invoked.  Otherwise it is used when we are about to start
+   * running as a background daemon, or when we are about to run a unit test
+   * in a subprocess.  Unlike the subsys_fns_t.prefork callback, it is run
+   * from the child process.
+   *
+   * Note that we do not invoke this function when the child process's only
+   * purpose is to call exec() and run another program.
    */
   void (*postfork)(void);
 
   /**
    * Free any thread-local resources held by this subsystem. Called before
    * the thread exits.
+   *
+   * This function is not allowed to fail.
+   *
+   * \bug Note that this callback is currently buggy: See \ticket{32103}.
    */
   void (*thread_cleanup)(void);
 
@@ -86,18 +120,28 @@ typedef struct subsys_fns_t {
    * Free all resources held by this subsystem.
    *
    * This function is not allowed to fail.
+   *
+   * Subsystems are shut down when Tor is about to exit or return control to
+   * an embedding program. This callback must return the process to a state
+   * such that subsys_fns_t.init will succeed if invoked again.
    **/
   void (*shutdown)(void);
 
   /**
    * A config_format_t describing all of the torrc fields owned by this
    * subsystem.
+   *
+   * This object, if present, is registered in a confmgr_t for Tor's options,
+   * and used to parse option fields from the command line and torrc file.
    **/
   const struct config_format_t *options_format;
 
   /**
    * A config_format_t describing all of the DataDir/state fields owned by
    * this subsystem.
+   *
+   * This object, if present, is registered in a confmgr_t for Tor's state,
+   * and used to parse state fields from the DataDir/state file.
    **/
   const struct config_format_t *state_format;
 
@@ -106,7 +150,11 @@ typedef struct subsys_fns_t {
    * on success, -1 on failure.
    *
    * It is safe to store the pointer to the object until set_options()
-   * is called again. */
+   * is called again.
+   *
+   * This function is only called after all the validation code defined
+   * by subsys_fns_t.options_format has passed.
+   **/
   int (*set_options)(void *);
 
   /* XXXX Add an implementation for options_act_reversible() later in this
@@ -118,6 +166,12 @@ typedef struct subsys_fns_t {
    *
    * It is safe to store the pointer to the object; set_state() is only
    * called on startup.
+   *
+   * This function is only called after all the validation code defined
+   * by subsys_fns_t.state_format has passed.
+   *
+   * This function will only be called once per invocation of Tor, since
+   * Tor does not reload its state while it is running.
    **/
   int (*set_state)(void *);
 
diff --git a/src/mainpage.dox b/src/mainpage.dox
index eb29eb5fa..575d8b7f4 100644
--- a/src/mainpage.dox
+++ b/src/mainpage.dox
@@ -30,7 +30,10 @@ Tor repository.
 
 @subpage intro
 
+ at subpage initialization
+
 @subpage dataflow
+
 **/
 
 /**





More information about the tor-commits mailing list