practracker: split shutdown code out of main.c

This is necessary to get the number of includes in main.c back under
control.  (In the future, we could just use the subsystem manager for
this kind of stuff.)
This commit is contained in:
Nick Mathewson 2019-03-14 09:37:44 -04:00
parent 4bdff5e3e9
commit ab6ddc7a33
6 changed files with 240 additions and 164 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/shutdown.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/cpuworker.h"
@ -24,55 +25,35 @@
#include "core/or/channel.h"
#include "core/or/channelpadding.h"
#include "core/or/circuitpadding.h"
#include "core/or/channeltls.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/command.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
#include "core/or/dos.h"
#include "core/or/policies.h"
#include "core/or/protover.h"
#include "core/or/relay.h"
#include "core/or/scheduler.h"
#include "core/or/status.h"
#include "core/or/versions.h"
#include "feature/api/tor_api.h"
#include "feature/api/tor_api_internal.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/entrynodes.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/process_descs.h"
#include "feature/dircache/consdiffmgr.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirparse/routerparse.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_cache.h"
#include "feature/nodelist/authcert.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/dns.h"
#include "feature/relay/ext_orport.h"
#include "feature/relay/onion_queue.h"
#include "feature/relay/routerkeys.h"
#include "feature/relay/routermode.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/rend/rendservice.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/predict_ports.h"
#include "feature/stats/rephist.h"
#include "lib/compress/compress.h"
#include "lib/buf/buffers.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_s2k.h"
#include "lib/geoip/geoip.h"
#include "lib/net/resolve.h"
#include "lib/process/waitpid.h"
@ -92,7 +73,6 @@
#include <event2/event.h>
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/authmode.h"
#include "feature/dirauth/shared_random.h"
@ -113,8 +93,6 @@
#include <systemd/sd-daemon.h>
#endif /* defined(HAVE_SYSTEMD) */
void evdns_shutdown(int);
#ifdef HAVE_RUST
// helper function defined in Rust to output a log message indicating if tor is
// running with Rust enabled. See src/rust/tor_util
@ -744,87 +722,6 @@ release_lockfile(void)
}
}
/** Free all memory that we might have allocated somewhere.
* If <b>postfork</b>, we are a worker process and we want to free
* only the parts of memory that we won't touch. If !<b>postfork</b>,
* Tor is shutting down and we should free everything.
*
* Helps us find the real leaks with sanitizers and the like. Also valgrind
* should then report 0 reachable in its leak report (in an ideal world --
* in practice libevent, SSL, libc etc never quite free everything). */
void
tor_free_all(int postfork)
{
if (!postfork) {
evdns_shutdown(1);
}
geoip_free_all();
geoip_stats_free_all();
dirvote_free_all();
routerlist_free_all();
networkstatus_free_all();
addressmap_free_all();
dirserv_free_fingerprint_list();
dirserv_free_all();
dirserv_clear_measured_bw_cache();
rend_cache_free_all();
rend_service_authorization_free_all();
rep_hist_free_all();
dns_free_all();
clear_pending_onions();
circuit_free_all();
circpad_machines_free();
entry_guards_free_all();
pt_free_all();
channel_tls_free_all();
channel_free_all();
connection_free_all();
connection_edge_free_all();
scheduler_free_all();
nodelist_free_all();
microdesc_free_all();
routerparse_free_all();
ext_orport_free_all();
control_free_all();
protover_free_all();
bridges_free_all();
consdiffmgr_free_all();
hs_free_all();
dos_free_all();
circuitmux_ewma_free_all();
accounting_free_all();
protover_summary_cache_free_all();
if (!postfork) {
config_free_all();
or_state_free_all();
router_free_all();
routerkeys_free_all();
policies_free_all();
}
if (!postfork) {
#ifndef _WIN32
tor_getpwnam(NULL);
#endif
}
/* stuff in main.c */
tor_mainloop_disconnect_pubsub();
tor_mainloop_free_all();
if (!postfork) {
release_lockfile();
}
tor_libevent_free_all();
subsystems_shutdown();
/* Stuff in util.c and address.c*/
if (!postfork) {
esc_router_info(NULL);
}
}
/**
* Remove the specified file, and log a warning if the operation fails for
* any reason other than the file not existing. Ignores NULL filenames.
@ -838,50 +735,6 @@ tor_remove_file(const char *filename)
}
}
/** Do whatever cleanup is necessary before shutting Tor down. */
void
tor_cleanup(void)
{
const or_options_t *options = get_options();
if (options->command == CMD_RUN_TOR) {
time_t now = time(NULL);
/* Remove our pid file. We don't care if there was an error when we
* unlink, nothing we could do about it anyways. */
tor_remove_file(options->PidFile);
/* Remove control port file */
tor_remove_file(options->ControlPortWriteToFile);
/* Remove cookie authentication file */
{
char *cookie_fname = get_controller_cookie_file_name();
tor_remove_file(cookie_fname);
tor_free(cookie_fname);
}
/* Remove Extended ORPort cookie authentication file */
{
char *cookie_fname = get_ext_or_auth_cookie_file_name();
tor_remove_file(cookie_fname);
tor_free(cookie_fname);
}
if (accounting_is_enabled(options))
accounting_record_bandwidth_usage(now, get_or_state());
or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */
or_state_save(now);
if (authdir_mode(options)) {
sr_save_and_cleanup();
}
if (authdir_mode_tests_reachability(options))
rep_hist_record_mtbf_data(now, 0);
keypin_close_journal();
}
timers_shutdown();
tor_free_all(0); /* We could move tor_free_all back into the ifdef below
later, if it makes shutdown unacceptably slow. But for
now, leave it here: it's helped us catch bugs in the
past. */
}
/** Read/create keys as needed, and echo our fingerprint to stdout. */
static int
do_list_fingerprint(void)
@ -1379,6 +1232,30 @@ run_tor_main_loop(void)
return do_main_loop();
}
/** Install the publish/subscribe relationships for all the subsystems. */
static void
pubsub_install(void)
{
pubsub_builder_t *builder = pubsub_builder_new();
int r = subsystems_add_pubsub(builder);
tor_assert(r == 0);
r = tor_mainloop_connect_pubsub(builder); // consumes builder
tor_assert(r == 0);
}
/** Connect the mainloop to its publish/subscribe message delivery events if
* appropriate, and configure the global channels appropriately. */
static void
pubsub_connect(void)
{
if (get_options()->command == CMD_RUN_TOR) {
tor_mainloop_connect_pubsub_events();
/* XXXX For each pubsub channel, its delivery strategy should be set at
* this XXXX point, using tor_mainloop_set_delivery_strategy().
*/
}
}
/* Main entry point for the Tor process. Called from tor_main(), and by
* anybody embedding Tor. */
int
@ -1411,13 +1288,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
}
#endif /* defined(NT_SERVICE) */
{
pubsub_builder_t *builder = pubsub_builder_new();
int r = subsystems_add_pubsub(builder);
tor_assert(r == 0);
r = tor_mainloop_connect_pubsub(builder); // consumes builder
tor_assert(r == 0);
}
pubsub_install();
{
int init_rv = tor_init(argc, argv);
@ -1428,12 +1299,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg)
}
}
if (get_options()->command == CMD_RUN_TOR) {
tor_mainloop_connect_pubsub_events();
/* XXXX For each pubsub channel, its delivery strategy should be set at
* this XXXX point, using tor_mainloop_set_delivery_strategy().
*/
}
pubsub_connect();
if (get_options()->Sandbox && get_options()->command == CMD_RUN_TOR) {
sandbox_cfg_t* cfg = sandbox_init_filter();

View File

@ -21,9 +21,6 @@ void release_lockfile(void);
void tor_remove_file(const char *filename);
void tor_cleanup(void);
void tor_free_all(int postfork);
int tor_init(int argc, char **argv);
int run_tor_main_loop(void);

View File

@ -24,6 +24,7 @@
#include "app/config/config.h"
#include "app/main/main.h"
#include "app/main/ntmain.h"
#include "app/main/shutdown.h"
#include "core/mainloop/mainloop.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/fs/winlib.h"

192
src/app/main/shutdown.c Normal file
View File

@ -0,0 +1,192 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* @file shutdown.c
* @brief Code to free global resources used by Tor.
*
* In the future, this should all be handled by the subsystem manager. */
#include "core/or/or.h"
#include "app/config/config.h"
#include "app/config/statefile.h"
#include "app/main/main.h"
#include "app/main/shutdown.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/mainloop_pubsub.h"
#include "core/or/channeltls.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitpadding.h"
#include "core/or/connection_edge.h"
#include "core/or/dos.h"
#include "core/or/policies.h"
#include "core/or/protover.h"
#include "core/or/scheduler.h"
#include "core/or/versions.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/entrynodes.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
#include "feature/control/control.h"
#include "feature/dirauth/authmode.h"
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/keypin.h"
#include "feature/dirauth/process_descs.h"
#include "feature/dirauth/shared_random.h"
#include "feature/dircache/consdiffmgr.h"
#include "feature/dircache/dirserv.h"
#include "feature/dirparse/routerparse.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_common.h"
#include "feature/nodelist/microdesc.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/dns.h"
#include "feature/relay/ext_orport.h"
#include "feature/relay/onion_queue.h"
#include "feature/relay/routerkeys.h"
#include "feature/rend/rendcache.h"
#include "feature/rend/rendclient.h"
#include "feature/stats/geoip_stats.h"
#include "feature/stats/rephist.h"
#include "lib/evloop/compat_libevent.h"
#include "lib/geoip/geoip.h"
#include "src/feature/relay/router.h"
void evdns_shutdown(int);
/** Do whatever cleanup is necessary before shutting Tor down. */
void
tor_cleanup(void)
{
const or_options_t *options = get_options();
if (options->command == CMD_RUN_TOR) {
time_t now = time(NULL);
/* Remove our pid file. We don't care if there was an error when we
* unlink, nothing we could do about it anyways. */
tor_remove_file(options->PidFile);
/* Remove control port file */
tor_remove_file(options->ControlPortWriteToFile);
/* Remove cookie authentication file */
{
char *cookie_fname = get_controller_cookie_file_name();
tor_remove_file(cookie_fname);
tor_free(cookie_fname);
}
/* Remove Extended ORPort cookie authentication file */
{
char *cookie_fname = get_ext_or_auth_cookie_file_name();
tor_remove_file(cookie_fname);
tor_free(cookie_fname);
}
if (accounting_is_enabled(options))
accounting_record_bandwidth_usage(now, get_or_state());
or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */
or_state_save(now);
if (authdir_mode(options)) {
sr_save_and_cleanup();
}
if (authdir_mode_tests_reachability(options))
rep_hist_record_mtbf_data(now, 0);
keypin_close_journal();
}
timers_shutdown();
tor_free_all(0); /* We could move tor_free_all back into the ifdef below
later, if it makes shutdown unacceptably slow. But for
now, leave it here: it's helped us catch bugs in the
past. */
}
/** Free all memory that we might have allocated somewhere.
* If <b>postfork</b>, we are a worker process and we want to free
* only the parts of memory that we won't touch. If !<b>postfork</b>,
* Tor is shutting down and we should free everything.
*
* Helps us find the real leaks with sanitizers and the like. Also valgrind
* should then report 0 reachable in its leak report (in an ideal world --
* in practice libevent, SSL, libc etc never quite free everything). */
void
tor_free_all(int postfork)
{
if (!postfork) {
evdns_shutdown(1);
}
geoip_free_all();
geoip_stats_free_all();
dirvote_free_all();
routerlist_free_all();
networkstatus_free_all();
addressmap_free_all();
dirserv_free_fingerprint_list();
dirserv_free_all();
dirserv_clear_measured_bw_cache();
rend_cache_free_all();
rend_service_authorization_free_all();
rep_hist_free_all();
dns_free_all();
clear_pending_onions();
circuit_free_all();
circpad_machines_free();
entry_guards_free_all();
pt_free_all();
channel_tls_free_all();
channel_free_all();
connection_free_all();
connection_edge_free_all();
scheduler_free_all();
nodelist_free_all();
microdesc_free_all();
routerparse_free_all();
ext_orport_free_all();
control_free_all();
protover_free_all();
bridges_free_all();
consdiffmgr_free_all();
hs_free_all();
dos_free_all();
circuitmux_ewma_free_all();
accounting_free_all();
protover_summary_cache_free_all();
if (!postfork) {
config_free_all();
or_state_free_all();
router_free_all();
routerkeys_free_all();
policies_free_all();
}
if (!postfork) {
#ifndef _WIN32
tor_getpwnam(NULL);
#endif
}
/* stuff in main.c */
tor_mainloop_disconnect_pubsub();
tor_mainloop_free_all();
if (!postfork) {
release_lockfile();
}
tor_libevent_free_all();
subsystems_shutdown();
/* Stuff in util.c and address.c*/
if (!postfork) {
esc_router_info(NULL);
}
}

18
src/app/main/shutdown.h Normal file
View File

@ -0,0 +1,18 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2018, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file shutdown.h
* \brief Header file for shutdown.c.
**/
#ifndef TOR_SHUTDOWN_H
#define TOR_SHUTDOWN_H
void tor_cleanup(void);
void tor_free_all(int postfork);
#endif /* !defined(TOR_SHUTDOWN_H) */

View File

@ -11,6 +11,7 @@ LIBTOR_APP_A_SOURCES = \
src/app/config/confparse.c \
src/app/config/statefile.c \
src/app/main/main.c \
src/app/main/shutdown.c \
src/app/main/subsystem_list.c \
src/app/main/subsysmgr.c \
src/core/crypto/hs_ntor.c \
@ -204,6 +205,7 @@ noinst_HEADERS += \
src/app/config/statefile.h \
src/app/main/main.h \
src/app/main/ntmain.h \
src/app/main/shutdown.h \
src/app/main/subsysmgr.h \
src/core/crypto/hs_ntor.h \
src/core/crypto/onion_crypto.h \