Code to manage the list of subsystems.

This commit is contained in:
Nick Mathewson 2018-11-01 11:51:33 -04:00
parent 0ce1f2d466
commit 7bb76b24cf
6 changed files with 184 additions and 0 deletions

View File

@ -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));

130
src/app/main/subsysmgr.c Normal file
View File

@ -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;
}
}

20
src/app/main/subsysmgr.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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 \

View File

@ -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