tor  master
Macros | Functions | Variables
main.c File Reference

Toplevel module. Handles signals, multiplexes between connections, implements main loop, and drives scheduled events. More...

#include "or.h"
#include "addressmap.h"
#include "backtrace.h"
#include "bridges.h"
#include "buffers.h"
#include "buffers_tls.h"
#include "channel.h"
#include "channeltls.h"
#include "channelpadding.h"
#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
#include "circuitmux_ewma.h"
#include "command.h"
#include "compress.h"
#include "config.h"
#include "confparse.h"
#include "connection.h"
#include "connection_edge.h"
#include "connection_or.h"
#include "consdiffmgr.h"
#include "control.h"
#include "cpuworker.h"
#include "crypto_s2k.h"
#include "crypto_rand.h"
#include "directory.h"
#include "dirserv.h"
#include "dns.h"
#include "dnsserv.h"
#include "dos.h"
#include "entrynodes.h"
#include "geoip.h"
#include "hibernate.h"
#include "hs_cache.h"
#include "hs_circuitmap.h"
#include "hs_client.h"
#include "keypin.h"
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "ntmain.h"
#include "onion.h"
#include "periodic.h"
#include "policies.h"
#include "protover.h"
#include "transports.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
#include "rephist.h"
#include "router.h"
#include "routerkeys.h"
#include "routerlist.h"
#include "routerparse.h"
#include "scheduler.h"
#include "statefile.h"
#include "status.h"
#include "tor_api.h"
#include "tor_api_internal.h"
#include "util_process.h"
#include "ext_orport.h"
#include "memarea.h"
#include "sandbox.h"
#include <event2/event.h>
#include "dirauth/dirvote.h"
#include "dirauth/mode.h"
#include "dirauth/shared_random.h"

Macros

#define MAIN_PRIVATE
 
#define MAX_SIGNEWNYM_RATE   10
 
#define GREEDY_DESCRIPTOR_RETRY_INTERVAL   (10)
 
#define LAZY_DESCRIPTOR_RETRY_INTERVAL   (60)
 
#define CALLBACK(name)   static int name ## _callback(time_t, const or_options_t *)
 
#define CALLBACK(name, r, f)   PERIODIC_EVENT(name, r, f)
 
#define NAMED_CALLBACK(name)   STMT_BEGIN name ## _event = find_periodic_event( #name ); STMT_END
 
#define LONGEST_TIMER_PERIOD   (30 * 86400)
 
#define ENTROPY_INTERVAL   (60*60)
 
#define SAVE_STABILITY_INTERVAL   (30*60)
 
#define CHECK_V3_CERTIFICATE_INTERVAL   (5*60)
 
#define NS_EXPIRY_SLOP   (24*60*60)
 
#define CHECK_EXPIRED_NS_INTERVAL   (2*60)
 
#define CHECK_WRITE_STATS_INTERVAL   (60*60)
 
#define CHANNEL_CHECK_INTERVAL   (60*60)
 
#define CLEAN_CACHES_INTERVAL   (30*60)
 
#define RETRY_DNS_INTERVAL   (10*60)
 
#define CHECK_DESCRIPTOR_INTERVAL   (60)
 
#define BANDWIDTH_RECHECK_INTERVAL   (12*60*60)
 
#define BRIDGE_STATUSFILE_INTERVAL   (30*60)
 
#define CDM_CLEAN_CALLBACK_INTERVAL   600
 
#define NUM_JUMPED_SECONDS_BEFORE_WARN   100
 
#define NUM_IDLE_SECONDS_BEFORE_WARN   3600
 
#define UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST   (6*60*60)
 
#define UNIX_ONLY   1
 
#define OPEN(name)   sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name))
 
#define OPEN_DATADIR(name)   sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name))
 
#define OPEN_DATADIR2(name, name2)   sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2((name), (name2)))
 
#define OPEN_DATADIR_SUFFIX(name, suffix)
 
#define OPEN_DATADIR2_SUFFIX(name, name2, suffix)
 
#define OPEN_KEY_DIRECTORY()   sandbox_cfg_allow_open_filename(&cfg, tor_strdup(options->KeyDirectory))
 
#define OPEN_CACHEDIR(name)   sandbox_cfg_allow_open_filename(&cfg, get_cachedir_fname(name))
 
#define OPEN_CACHEDIR_SUFFIX(name, suffix)
 
#define OPEN_KEYDIR(name)   sandbox_cfg_allow_open_filename(&cfg, get_keydir_fname(name))
 
#define OPEN_KEYDIR_SUFFIX(name, suffix)
 
#define RENAME_SUFFIX(name, suffix)
 
#define RENAME_SUFFIX2(prefix, name, suffix)
 
#define RENAME_CACHEDIR_SUFFIX(name, suffix)
 
#define RENAME_KEYDIR_SUFFIX(name, suffix)
 
#define STAT_DATADIR(name)   sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname(name))
 
#define STAT_CACHEDIR(name)   sandbox_cfg_allow_stat_filename(&cfg, get_cachedir_fname(name))
 
#define STAT_DATADIR2(name, name2)   sandbox_cfg_allow_stat_filename(&cfg, get_datadir_fname2((name), (name2)))
 
#define STAT_KEY_DIRECTORY()   sandbox_cfg_allow_stat_filename(&cfg, tor_strdup(options->KeyDirectory))
 

Functions

void evdns_shutdown (int)
 
int have_completed_a_circuit (void)
 
void note_that_we_completed_a_circuit (void)
 
void note_that_we_maybe_cant_complete_circuits (void)
 
int connection_add_impl (connection_t *conn, int is_connecting)
 
void connection_unregister_events (connection_t *conn)
 
int connection_remove (connection_t *conn)
 
STATIC void init_connection_lists (void)
 
void add_connection_to_closeable_list (connection_t *conn)
 
int connection_is_on_closeable_list (connection_t *conn)
 
int connection_in_array (connection_t *conn)
 
 MOCK_IMPL (smartlist_t *, get_connection_array,(void))
 
 MOCK_IMPL (uint64_t, get_bytes_read,(void))
 
 MOCK_IMPL (uint64_t, get_bytes_written,(void))
 
void stats_increment_bytes_read_and_written (uint64_t r, uint64_t w)
 
void connection_watch_events (connection_t *conn, watchable_events_t events)
 
int connection_is_reading (connection_t *conn)
 
void reset_main_loop_counters (void)
 
uint64_t get_main_loop_success_count (void)
 
uint64_t get_main_loop_error_count (void)
 
uint64_t get_main_loop_idle_count (void)
 
 MOCK_IMPL (void, connection_stop_reading,(connection_t *conn))
 
 MOCK_IMPL (void, connection_start_reading,(connection_t *conn))
 
int connection_is_writing (connection_t *conn)
 
 MOCK_IMPL (void, connection_stop_writing,(connection_t *conn))
 
 MOCK_IMPL (void, connection_start_writing,(connection_t *conn))
 
void tor_shutdown_event_loop_and_exit (int exitcode)
 
int tor_event_loop_shutdown_is_pending (void)
 
void connection_stop_reading_from_linked_conn (connection_t *conn)
 
STATIC void close_closeable_connections (void)
 
 MOCK_IMPL (int, connection_count_moribund,(void))
 
void directory_all_unreachable (time_t now)
 
void directory_info_has_arrived (time_t now, int from_cache, int suppress_logs)
 
unsigned get_signewnym_epoch (void)
 
 CALLBACK (add_entropy)
 
 CALLBACK (check_authority_cert)
 
 CALLBACK (check_canonical_channels)
 
 CALLBACK (check_descriptor)
 
 CALLBACK (check_dns_honesty)
 
 CALLBACK (check_ed_keys)
 
 CALLBACK (check_expired_networkstatus)
 
 CALLBACK (check_for_reachability_bw)
 
 CALLBACK (check_onion_keys_expiry_time)
 
 CALLBACK (clean_caches)
 
 CALLBACK (clean_consdiffmgr)
 
 CALLBACK (dirvote)
 
 CALLBACK (downrate_stability)
 
 CALLBACK (expire_old_ciruits_serverside)
 
 CALLBACK (fetch_networkstatus)
 
 CALLBACK (heartbeat)
 
 CALLBACK (hs_service)
 
 CALLBACK (launch_descriptor_fetches)
 
 CALLBACK (launch_reachability_tests)
 
 CALLBACK (reachability_warnings)
 
 CALLBACK (record_bridge_stats)
 
 CALLBACK (rend_cache_failure_clean)
 
 CALLBACK (reset_padding_counts)
 
 CALLBACK (retry_dns)
 
 CALLBACK (retry_listeners)
 
 CALLBACK (rotate_onion_key)
 
 CALLBACK (rotate_x509_certificate)
 
 CALLBACK (save_stability)
 
 CALLBACK (save_state)
 
 CALLBACK (write_bridge_ns)
 
 CALLBACK (write_stats_file)
 
void reset_all_main_loop_timers (void)
 
STATIC int get_my_roles (const or_options_t *options)
 
STATIC void initialize_periodic_events (void)
 
STATIC void teardown_periodic_events (void)
 
void rescan_periodic_events (const or_options_t *options)
 
void periodic_events_on_new_options (const or_options_t *options)
 
void reschedule_descriptor_update_check (void)
 
void reschedule_directory_downloads (void)
 
void mainloop_schedule_postloop_cleanup (void)
 
void reschedule_dirvote (const or_options_t *options)
 
void reschedule_or_state_save (void)
 
void reschedule_per_second_timer (void)
 
void update_current_time (time_t now)
 
void ip_address_changed (int at_interface)
 
void dns_servers_relaunch_checks (void)
 
STATIC void initialize_mainloop_events (void)
 
int do_main_loop (void)
 
 MOCK_IMPL (long, get_uptime,(void))
 
 MOCK_IMPL (void, reset_uptime,(void))
 
void handle_signals (void)
 
void activate_signal (int signal_num)
 
int tor_init (int argc, char *argv[])
 
int try_locking (const or_options_t *options, int err_if_locked)
 
int have_lockfile (void)
 
void release_lockfile (void)
 
void tor_free_all (int postfork)
 
void tor_remove_file (const char *filename)
 
void tor_cleanup (void)
 
int tor_run_main (const tor_main_configuration_t *tor_cfg)
 

Variables

token_bucket_rw_t global_bucket
 
token_bucket_rw_t global_relayed_bucket
 
time_t time_of_process_start = 0
 
STATIC smartlist_tconnection_array = NULL
 
int quiet_level = 0
 
STATIC periodic_event_item_t periodic_events []
 

Detailed Description

Toplevel module. Handles signals, multiplexes between connections, implements main loop, and drives scheduled events.

For the main loop itself; see run_main_loop_once(). It invokes the rest of Tor mostly through Libevent callbacks. Libevent callbacks can happen when a timer elapses, a signal is received, a socket is ready to read or write, or an event is manually activated.

Most events in Tor are driven from these callbacks:

Other events are used for specific purposes, or for building more complex control structures. If you search for usage of tor_libevent_new(), you will find all the events that we construct in Tor.

Tor has numerous housekeeping operations that need to happen regularly. They are handled in different ways:

Macro Definition Documentation

◆ GREEDY_DESCRIPTOR_RETRY_INTERVAL

#define GREEDY_DESCRIPTOR_RETRY_INTERVAL   (10)

How often do we check for router descriptors that we should download when we have too little directory info?

◆ LAZY_DESCRIPTOR_RETRY_INTERVAL

#define LAZY_DESCRIPTOR_RETRY_INTERVAL   (60)

How often do we check for router descriptors that we should download when we have enough directory info?

◆ MAX_SIGNEWNYM_RATE

#define MAX_SIGNEWNYM_RATE   10

How often will we honor SIGNEWNYM requests?

◆ OPEN_CACHEDIR_SUFFIX

#define OPEN_CACHEDIR_SUFFIX (   name,
  suffix 
)
Value:
do { \
OPEN_CACHEDIR(name); \
OPEN_CACHEDIR(name suffix); \
} while (0)

◆ OPEN_DATADIR2_SUFFIX

#define OPEN_DATADIR2_SUFFIX (   name,
  name2,
  suffix 
)
Value:
do { \
OPEN_DATADIR2(name, name2); \
OPEN_DATADIR2(name, name2 suffix); \
} while (0)

◆ OPEN_DATADIR_SUFFIX

#define OPEN_DATADIR_SUFFIX (   name,
  suffix 
)
Value:
do { \
OPEN_DATADIR(name); \
OPEN_DATADIR(name suffix); \
} while (0)

◆ OPEN_KEYDIR_SUFFIX

#define OPEN_KEYDIR_SUFFIX (   name,
  suffix 
)
Value:
do { \
OPEN_KEYDIR(name); \
OPEN_KEYDIR(name suffix); \
} while (0)

◆ RENAME_CACHEDIR_SUFFIX

#define RENAME_CACHEDIR_SUFFIX (   name,
  suffix 
)
Value:
sandbox_cfg_allow_rename(&cfg, \
get_cachedir_fname(name suffix), \
get_cachedir_fname(name))

◆ RENAME_KEYDIR_SUFFIX

#define RENAME_KEYDIR_SUFFIX (   name,
  suffix 
)
Value:
sandbox_cfg_allow_rename(&cfg, \
get_keydir_fname(name suffix), \
get_keydir_fname(name))

◆ RENAME_SUFFIX

#define RENAME_SUFFIX (   name,
  suffix 
)
Value:
sandbox_cfg_allow_rename(&cfg, \
get_datadir_fname(name suffix), \
get_datadir_fname(name))

◆ RENAME_SUFFIX2

#define RENAME_SUFFIX2 (   prefix,
  name,
  suffix 
)
Value:
sandbox_cfg_allow_rename(&cfg, \
get_datadir_fname2(prefix, name suffix), \
get_datadir_fname2(prefix, name))

Function Documentation

◆ add_connection_to_closeable_list()

void add_connection_to_closeable_list ( connection_t conn)

Schedule conn to be closed.

Here is the call graph for this function:

◆ close_closeable_connections()

STATIC void close_closeable_connections ( void  )

Close all connections that have been scheduled to get closed.

◆ connection_add_impl()

int connection_add_impl ( connection_t conn,
int  is_connecting 
)

Add conn to the array of connections that we can poll on. The connection's socket must be set; the connection starts out non-reading and non-writing.

◆ connection_in_array()

int connection_in_array ( connection_t conn)

Return true iff conn is in the current poll array.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connection_is_on_closeable_list()

int connection_is_on_closeable_list ( connection_t conn)

Return 1 if conn is on the closeable list, else return 0.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connection_is_reading()

int connection_is_reading ( connection_t conn)

Return true iff conn is listening for read events.

◆ connection_is_writing()

int connection_is_writing ( connection_t conn)

Return true iff conn is listening for write events.

◆ connection_remove()

int connection_remove ( connection_t conn)

Remove the connection from the global list, and remove the corresponding poll entry. Calling this function will shift the last connection (if any) into the position occupied by conn.

◆ connection_stop_reading_from_linked_conn()

void connection_stop_reading_from_linked_conn ( connection_t conn)

Tell the main loop to stop reading bytes into conn from its linked connection, if is currently doing so. Called by connection_stop_reading, connection_stop_writing, and connection_read.

Here is the call graph for this function:

◆ connection_unregister_events()

void connection_unregister_events ( connection_t conn)

Tell libevent that we don't care about conn any more.

◆ connection_watch_events()

void connection_watch_events ( connection_t conn,
watchable_events_t  events 
)

Set the event mask on conn to events. (The event mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)

◆ directory_all_unreachable()

void directory_all_unreachable ( time_t  now)

We've just tried every dirserver we know about, and none of them were reachable. Assume the network is down. Change state so next time an application connection arrives we'll delay it and try another directory fetch. Kill off all the circuit_wait streams that are waiting now, since they will all timeout anyway.

Here is the call graph for this function:

◆ directory_info_has_arrived()

void directory_info_has_arrived ( time_t  now,
int  from_cache,
int  suppress_logs 
)

This function is called whenever we successfully pull down some new network statuses or server descriptors.

Here is the call graph for this function:

◆ dns_servers_relaunch_checks()

void dns_servers_relaunch_checks ( void  )

Forget what we've learned about the correctness of our DNS servers, and start learning again.

Here is the call graph for this function:

◆ do_main_loop()

int do_main_loop ( void  )

Tor main loop.

Here is the call graph for this function:

◆ get_main_loop_error_count()

uint64_t get_main_loop_error_count ( void  )

Get the main loop error counter.

◆ get_main_loop_idle_count()

uint64_t get_main_loop_idle_count ( void  )

Get the main loop idle counter.

◆ get_main_loop_success_count()

uint64_t get_main_loop_success_count ( void  )

Get the main loop success counter.

◆ get_my_roles()

STATIC int get_my_roles ( const or_options_t options)

Return a bitmask of the roles this tor instance is configured for using the given options.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_signewnym_epoch()

unsigned get_signewnym_epoch ( void  )

Return the number of times that signewnym has been called.

◆ handle_signals()

void handle_signals ( void  )

Set up the signal handler events for this process, and register them with libevent if appropriate.

◆ have_completed_a_circuit()

int have_completed_a_circuit ( void  )

Return 1 if we have successfully built a circuit, and nothing has changed to make us think that maybe we can't.

Here is the caller graph for this function:

◆ have_lockfile()

int have_lockfile ( void  )

Return true iff we've successfully acquired the lock file.

◆ init_connection_lists()

STATIC void init_connection_lists ( void  )

Initialize the global connection list, closeable connection list, and active connection list.

Here is the caller graph for this function:

◆ initialize_mainloop_events()

STATIC void initialize_mainloop_events ( void  )

Initialize some mainloop_event_t objects that we require.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ initialize_periodic_events()

STATIC void initialize_periodic_events ( void  )

Set up all the members of periodic_events[], and configure them all to be launched from a callback.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ip_address_changed()

void ip_address_changed ( int  at_interface)

Called when our IP address seems to have changed. at_interface should be true if we detected a change in our interface, and false if we detected a change in our published address.

◆ mainloop_schedule_postloop_cleanup()

void mainloop_schedule_postloop_cleanup ( void  )

Schedule a post-loop event to clean up marked channels, connections, and circuits.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MOCK_IMPL() [1/10]

MOCK_IMPL ( smartlist_t ,
get_connection_array  ,
(void)   
)

Set *array to an array of all connections. *array must not be modified.

◆ MOCK_IMPL() [2/10]

MOCK_IMPL ( uint64_t  ,
get_bytes_read  ,
(void)   
)

Return the amount of network traffic read, in bytes, over the life of this process.

◆ MOCK_IMPL() [3/10]

MOCK_IMPL ( uint64_t  ,
get_bytes_written  ,
(void)   
)

Return the amount of network traffic read, in bytes, over the life of this process.

◆ MOCK_IMPL() [4/10]

MOCK_IMPL ( void  ,
connection_stop_reading  ,
(connection_t *conn)   
)

Tell the main loop to stop notifying conn of any read events.

◆ MOCK_IMPL() [5/10]

MOCK_IMPL ( void  ,
connection_start_reading  ,
(connection_t *conn)   
)

Tell the main loop to start notifying conn of any read events.

◆ MOCK_IMPL() [6/10]

MOCK_IMPL ( void  ,
connection_stop_writing  ,
(connection_t *conn)   
)

Tell the main loop to stop notifying conn of any write events.

◆ MOCK_IMPL() [7/10]

MOCK_IMPL ( void  ,
connection_start_writing  ,
(connection_t *conn)   
)

Tell the main loop to start notifying conn of any write events.

◆ MOCK_IMPL() [8/10]

MOCK_IMPL ( int  ,
connection_count_moribund  ,
(void)   
)

Count moribund connections for the OOS handler

◆ MOCK_IMPL() [9/10]

MOCK_IMPL ( long  ,
get_uptime  ,
(void)   
)

Returns Tor's uptime.

◆ MOCK_IMPL() [10/10]

MOCK_IMPL ( void  ,
reset_uptime  ,
(void)   
)

Reset Tor's uptime.

◆ note_that_we_completed_a_circuit()

void note_that_we_completed_a_circuit ( void  )

Note that we have successfully built a circuit, so that reachability testing and introduction points and so on may be attempted.

◆ note_that_we_maybe_cant_complete_circuits()

void note_that_we_maybe_cant_complete_circuits ( void  )

Note that something has happened (like a clock jump, or DisableNetwork) to make us think that maybe we can't complete circuits.

Here is the caller graph for this function:

◆ release_lockfile()

void release_lockfile ( void  )

If we have successfully acquired the lock file, release it.

Here is the call graph for this function:

◆ rescan_periodic_events()

void rescan_periodic_events ( const or_options_t options)

Do a pass at all our periodic events, disable those we don't need anymore and enable those we need now using the given options.

Here is the call graph for this function:

◆ reschedule_descriptor_update_check()

void reschedule_descriptor_update_check ( void  )

Update our schedule so that we'll check whether we need to update our descriptor immediately, rather than after up to CHECK_DESCRIPTOR_INTERVAL seconds.

Here is the call graph for this function:

◆ reschedule_directory_downloads()

void reschedule_directory_downloads ( void  )

Update our schedule so that we'll check whether we need to fetch directory info immediately.

Here is the call graph for this function:

◆ reschedule_dirvote()

void reschedule_dirvote ( const or_options_t options)

Reschedule the directory-authority voting event. Run this whenever the schedule has changed.

◆ reschedule_or_state_save()

void reschedule_or_state_save ( void  )

Reschedule the event for saving the state file.

Run this when the state becomes dirty.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reschedule_per_second_timer()

void reschedule_per_second_timer ( void  )

Enable or disable the per-second timer as appropriate, creating it if necessary.

Here is the call graph for this function:

◆ reset_all_main_loop_timers()

void reset_all_main_loop_timers ( void  )

Reset all the periodic events so we'll do all our actions again as if we just started up. Useful if our clock just moved back a long time from the future, so we don't wait until that future arrives again before acting.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ reset_main_loop_counters()

void reset_main_loop_counters ( void  )

Reset our main loop counters.

◆ stats_increment_bytes_read_and_written()

void stats_increment_bytes_read_and_written ( uint64_t  r,
uint64_t  w 
)

Increment the amount of network traffic read and written, over the life of this process.

◆ tor_cleanup()

void tor_cleanup ( void  )

Do whatever cleanup is necessary before shutting Tor down.

Here is the call graph for this function:

◆ tor_event_loop_shutdown_is_pending()

int tor_event_loop_shutdown_is_pending ( void  )

Return true iff tor_shutdown_event_loop_and_exit() has been called.

◆ tor_free_all()

void tor_free_all ( int  postfork)

Free all memory that we might have allocated somewhere. If postfork, we are a worker process and we want to free only the parts of memory that we won't touch. If !postfork, Tor is shutting down and we should free everything.

Helps us find the real leaks with dmalloc 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).

◆ tor_init()

int tor_init ( int  argc,
char *  argv[] 
)

Main entry point for the Tor command-line client. Return 0 on "success", negative on "failure", and positive on "success and exit".

Here is the call graph for this function:
Here is the caller graph for this function:

◆ tor_remove_file()

void tor_remove_file ( const char *  filename)

Remove the specified file, and log a warning if the operation fails for any reason other than the file not existing. Ignores NULL filenames.

Here is the caller graph for this function:

◆ tor_run_main()

int tor_run_main ( const tor_main_configuration_t )

Run the tor process, as if from the command line.

The command line arguments from tor_main_configuration_set_command_line() are taken as if they had been passed to main().

This function will not return until Tor is done running. It returns zero on success, and nonzero on failure.

If you want to control when Tor exits, make sure to configure a control socket. The OwningControllerFD option may be helpful there.

BUG 23847: Sometimes, if you call tor_main a second time (after it has returned), Tor may crash or behave strangely. We have fixed all issues of this type that we could find, but more may remain.

LIMITATION: You cannot run more than one instance of Tor in the same process at the same time. Concurrent calls will cause undefined behavior. We do not currently have plans to change this.

LIMITATION: While we will try to fix any problems found here, you should be aware that Tor was originally written to run as its own process, and that the functionality of this file was added later. If you find any bugs or strange behavior, please report them, and we'll try to straighten them out.

◆ tor_shutdown_event_loop_and_exit()

void tor_shutdown_event_loop_and_exit ( int  exitcode)

After finishing the current callback (if any), shut down the main loop, clean up the process, and exit with exitcode.

◆ try_locking()

int try_locking ( const or_options_t options,
int  err_if_locked 
)

Try to grab the lock file described in options, if we do not already have it. If err_if_locked is true, warn if somebody else is holding the lock, and exit if we can't get it after waiting. Otherwise, return -1 if we can't get the lockfile. Return 0 on success.

◆ update_current_time()

void update_current_time ( time_t  now)

Set the current time to "now", which should be the value returned by time(). Check for clock jumps and track the total number of seconds we have been running.

How much clock jumping do we tolerate?

How much idleness do we tolerate?

Variable Documentation

◆ connection_array

STATIC smartlist_t* connection_array = NULL

Smartlist of all open connections.

◆ quiet_level

int quiet_level = 0

Decides our behavior when no logs are configured/before any logs have been configured. For 0, we log notice to stdout as normal. For 1, we log warnings only. For 2, we log nothing.

◆ signal_event

struct event* signal_event

Pointer to hold the event object constructed for this signal.

◆ signal_value

int signal_value

A numeric code for this signal. Must match the signal value if try_to_register is true.

◆ time_of_process_start

time_t time_of_process_start = 0

What time did this process start up?

◆ try_to_register

int try_to_register

True if we should try to register this signal with libevent and catch corresponding posix signals. False otherwise.