Back to index

tor  0.2.3.18-rc
Defines | Typedefs | Enumerations | Functions | Variables
main.h File Reference

Header file for main.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define connection_add(conn)   connection_add_impl((conn), 0)
#define connection_add_connecting(conn)   connection_add_impl((conn), 1)

Typedefs

typedef enum watchable_events watchable_events_t
 Bitmask for events that we can turn on and off with connection_watch_events.

Enumerations

enum  watchable_events { READ_EVENT = 0x02, WRITE_EVENT = 0x04 }
 Bitmask for events that we can turn on and off with connection_watch_events. More...

Functions

int connection_add_impl (connection_t *conn, int is_connecting)
 Add conn to the array of connections that we can poll on.
int connection_remove (connection_t *conn)
 Remove the connection from the global list, and remove the corresponding poll entry.
void connection_unregister_events (connection_t *conn)
 Tell libevent that we don't care about conn any more.
int connection_in_array (connection_t *conn)
 Return true iff conn is in the current poll array.
void add_connection_to_closeable_list (connection_t *conn)
 Schedule conn to be closed.
int connection_is_on_closeable_list (connection_t *conn)
 Return 1 if conn is on the closeable list, else return 0.
smartlist_tget_connection_array (void)
 Set *array to an array of all connections, and *n to the length of the array.
uint64_t get_bytes_read (void)
 Provides the traffic read and written over the life of the process.
uint64_t get_bytes_written (void)
void connection_watch_events (connection_t *conn, watchable_events_t events)
 Set the event mask on conn to events.
int connection_is_reading (connection_t *conn)
 Return true iff conn is listening for read events.
void connection_stop_reading (connection_t *conn)
 Tell the main loop to stop notifying conn of any read events.
void connection_start_reading (connection_t *conn)
 Tell the main loop to start notifying conn of any read events.
int connection_is_writing (connection_t *conn)
 Return true iff conn is listening for write events.
void connection_stop_writing (connection_t *conn)
 Tell the main loop to stop notifying conn of any write events.
void connection_start_writing (connection_t *conn)
 Tell the main loop to start notifying conn of any write events.
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.
void directory_all_unreachable (time_t now)
 We've just tried every dirserver we know about, and none of them were reachable.
void directory_info_has_arrived (time_t now, int from_cache)
 This function is called whenever we successfully pull down some new network statuses or server descriptors.
void ip_address_changed (int at_interface)
 Called when our IP address seems to have changed.
void dns_servers_relaunch_checks (void)
 Forget what we've learned about the correctness of our DNS servers, and start learning again.
long get_uptime (void)
 Returns Tor's uptime.
unsigned get_signewnym_epoch (void)
 Return the number of times that signewnym has been called.
void handle_signals (int is_parent)
 Set up the signal handlers for either parent or child.
void process_signal (uintptr_t sig)
 Do the work of acting on a signal received in sig
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.
int have_lockfile (void)
 Return true iff we've successfully acquired the lock file.
void release_lockfile (void)
 If we have successfully acquired the lock file, release it.
void tor_cleanup (void)
 Do whatever cleanup is necessary before shutting Tor down.
void tor_free_all (int postfork)
 Free all memory that we might have allocated somewhere.
int tor_main (int argc, char *argv[])
 Main entry point for the Tor process.

Variables

int can_complete_circuit
 We set this to 1 when we've opened a circuit, so we can print a log entry to inform the user that Tor is working.

Detailed Description

Header file for main.c.

Definition in file main.h.


Define Documentation

#define connection_add (   conn)    connection_add_impl((conn), 0)

Definition at line 18 of file main.h.

#define connection_add_connecting (   conn)    connection_add_impl((conn), 1)

Definition at line 19 of file main.h.


Typedef Documentation

Bitmask for events that we can turn on and off with connection_watch_events.


Enumeration Type Documentation

Bitmask for events that we can turn on and off with connection_watch_events.

Enumerator:
READ_EVENT 

We want to know when a connection is readable.

WRITE_EVENT 

We want to know when a connection is writable.

Definition at line 32 of file main.h.

                              {
  /* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */
  READ_EVENT=0x02, 
  WRITE_EVENT=0x04 
} watchable_events_t;

Function Documentation

Schedule conn to be closed.

Definition at line 406 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 226 of file main.c.

{
  tor_assert(conn);
  tor_assert(SOCKET_OK(conn->s) ||
             conn->linked ||
             (conn->type == CONN_TYPE_AP &&
              TO_EDGE_CONN(conn)->is_dns_request));

  tor_assert(conn->conn_array_index == -1); /* can only connection_add once */
  conn->conn_array_index = smartlist_len(connection_array);
  smartlist_add(connection_array, conn);

#ifdef USE_BUFFEREVENTS
  if (connection_type_uses_bufferevent(conn)) {
    if (SOCKET_OK(conn->s) && !conn->linked) {

#ifdef _WIN32
      if (tor_libevent_using_iocp_bufferevents() &&
          get_options()->UserspaceIOCPBuffers) {
        set_buffer_lengths_to_zero(conn->s);
      }
#endif

      conn->bufev = bufferevent_socket_new(
                         tor_libevent_get_base(),
                         conn->s,
                         BEV_OPT_DEFER_CALLBACKS);
      if (!conn->bufev) {
        log_warn(LD_BUG, "Unable to create socket bufferevent");
        smartlist_del(connection_array, conn->conn_array_index);
        conn->conn_array_index = -1;
        return -1;
      }
      if (is_connecting) {
        /* Put the bufferevent into a "connecting" state so that we'll get
         * a "connected" event callback on successful write. */
        bufferevent_socket_connect(conn->bufev, NULL, 0);
      }
      connection_configure_bufferevent_callbacks(conn);
    } else if (conn->linked && conn->linked_conn &&
               connection_type_uses_bufferevent(conn->linked_conn)) {
      tor_assert(!(SOCKET_OK(conn->s)));
      if (!conn->bufev) {
        struct bufferevent *pair[2] = { NULL, NULL };
        if (bufferevent_pair_new(tor_libevent_get_base(),
                                 BEV_OPT_DEFER_CALLBACKS,
                                 pair) < 0) {
          log_warn(LD_BUG, "Unable to create bufferevent pair");
          smartlist_del(connection_array, conn->conn_array_index);
          conn->conn_array_index = -1;
          return -1;
        }
        tor_assert(pair[0]);
        conn->bufev = pair[0];
        conn->linked_conn->bufev = pair[1];
      } /* else the other side already was added, and got a bufferevent_pair */
      connection_configure_bufferevent_callbacks(conn);
    } else {
      tor_assert(!conn->linked);
    }

    if (conn->bufev)
      tor_assert(conn->inbuf == NULL);

    if (conn->linked_conn && conn->linked_conn->bufev)
      tor_assert(conn->linked_conn->inbuf == NULL);
  }
#else
  (void) is_connecting;
#endif

  if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) {
    conn->read_event = tor_event_new(tor_libevent_get_base(),
         conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
    conn->write_event = tor_event_new(tor_libevent_get_base(),
         conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
    /* XXXX CHECK FOR NULL RETURN! */
  }

  log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
            conn_type_to_string(conn->type), (int)conn->s, conn->address,
            smartlist_len(connection_array));

  return 0;
}

Here is the call graph for this function:

Return true iff conn is in the current poll array.

Definition at line 423 of file main.c.

{
  return smartlist_isin(connection_array, conn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 416 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff conn is listening for read events.

Definition at line 485 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn,
    return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
  );
  return conn->reading_from_linked_conn ||
    (conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
}

Here is the caller graph for this function:

Return true iff conn is listening for write events.

Definition at line 549 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn,
    return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
  );

  return conn->writing_to_linked_conn ||
    (conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
}

Here is the caller graph for this function:

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.

Definition at line 342 of file main.c.

{
  int current_index;
  connection_t *tmp;

  tor_assert(conn);

  log_debug(LD_NET,"removing socket %d (type %s), n_conns now %d",
            (int)conn->s, conn_type_to_string(conn->type),
            smartlist_len(connection_array));

  tor_assert(conn->conn_array_index >= 0);
  current_index = conn->conn_array_index;
  connection_unregister_events(conn); /* This is redundant, but cheap. */
  if (current_index == smartlist_len(connection_array)-1) { /* at the end */
    smartlist_del(connection_array, current_index);
    return 0;
  }

  /* replace this one with the one at the end */
  smartlist_del(connection_array, current_index);
  tmp = smartlist_get(connection_array, current_index);
  tmp->conn_array_index = current_index;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 523 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn, {
      bufferevent_enable(conn->bufev, EV_READ);
      return;
  });

  tor_assert(conn->read_event);

  if (conn->linked) {
    conn->reading_from_linked_conn = 1;
    if (connection_should_read_from_linked_conn(conn))
      connection_start_reading_from_linked_conn(conn);
  } else {
    if (event_add(conn->read_event, NULL))
      log_warn(LD_NET, "Error from libevent setting read event state for %d "
               "to watched: %s",
               (int)conn->s,
               tor_socket_strerror(tor_socket_errno(conn->s)));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 589 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn, {
      bufferevent_enable(conn->bufev, EV_WRITE);
      return;
  });

  tor_assert(conn->write_event);

  if (conn->linked) {
    conn->writing_to_linked_conn = 1;
    if (conn->linked_conn &&
        connection_should_read_from_linked_conn(conn->linked_conn))
      connection_start_reading_from_linked_conn(conn->linked_conn);
  } else {
    if (event_add(conn->write_event, NULL))
      log_warn(LD_NET, "Error from libevent setting write event state for %d "
               "to watched: %s",
               (int)conn->s,
               tor_socket_strerror(tor_socket_errno(conn->s)));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 498 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn, {
      bufferevent_disable(conn->bufev, EV_READ);
      return;
  });

  tor_assert(conn->read_event);

  if (conn->linked) {
    conn->reading_from_linked_conn = 0;
    connection_stop_reading_from_linked_conn(conn);
  } else {
    if (event_del(conn->read_event))
      log_warn(LD_NET, "Error from libevent setting read event state for %d "
               "to unwatched: %s",
               (int)conn->s,
               tor_socket_strerror(tor_socket_errno(conn->s)));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 660 of file main.c.

{
  tor_assert(conn);
  tor_assert(conn->linked == 1);

  if (conn->active_on_link) {
    conn->active_on_link = 0;
    /* FFFF We could keep an index here so we can smartlist_del
     * cleanly.  On the other hand, this doesn't show up on profiles,
     * so let's leave it alone for now. */
    smartlist_remove(active_linked_connection_lst, conn);
  } else {
    tor_assert(!smartlist_isin(active_linked_connection_lst, conn));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 563 of file main.c.

{
  tor_assert(conn);

  IF_HAS_BUFFEREVENT(conn, {
      bufferevent_disable(conn->bufev, EV_WRITE);
      return;
  });

  tor_assert(conn->write_event);

  if (conn->linked) {
    conn->writing_to_linked_conn = 0;
    if (conn->linked_conn)
      connection_stop_reading_from_linked_conn(conn->linked_conn);
  } else {
    if (event_del(conn->write_event))
      log_warn(LD_NET, "Error from libevent setting write event state for %d "
               "to unwatched: %s",
               (int)conn->s,
               tor_socket_strerror(tor_socket_errno(conn->s)));
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 314 of file main.c.

{
  if (conn->read_event) {
    if (event_del(conn->read_event))
      log_warn(LD_BUG, "Error removing read event for %d", (int)conn->s);
    tor_free(conn->read_event);
  }
  if (conn->write_event) {
    if (event_del(conn->write_event))
      log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
    tor_free(conn->write_event);
  }
#ifdef USE_BUFFEREVENTS
  if (conn->bufev) {
    bufferevent_free(conn->bufev);
    conn->bufev = NULL;
  }
#endif
  if (conn->type == CONN_TYPE_AP_DNS_LISTENER) {
    dnsserv_close_listener(conn);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Set the event mask on conn to events.

(The event mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)

Definition at line 459 of file main.c.

{
  IF_HAS_BUFFEREVENT(conn, {
      short ev = ((short)events) & (EV_READ|EV_WRITE);
      short old_ev = bufferevent_get_enabled(conn->bufev);
      if ((ev & ~old_ev) != 0) {
        bufferevent_enable(conn->bufev, ev);
      }
      if ((old_ev & ~ev) != 0) {
        bufferevent_disable(conn->bufev, old_ev & ~ev);
      }
      return;
  });
  if (events & READ_EVENT)
    connection_start_reading(conn);
  else
    connection_stop_reading(conn);

  if (events & WRITE_EVENT)
    connection_start_writing(conn);
  else
    connection_stop_writing(conn);
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 927 of file main.c.

{
  connection_t *conn;
  (void)now;

  stats_n_seconds_working=0; /* reset it */

  while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
                                              AP_CONN_STATE_CIRCUIT_WAIT))) {
    entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
    log_notice(LD_NET,
               "Is your network connection down? "
               "Failing connection to '%s:%d'.",
               safe_str_client(entry_conn->socks_request->address),
               entry_conn->socks_request->port);
    connection_mark_unattached_ap(entry_conn,
                                  END_STREAM_REASON_NET_UNREACHABLE);
  }
  control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void directory_info_has_arrived ( time_t  now,
int  from_cache 
)

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

Definition at line 951 of file main.c.

{
  const or_options_t *options = get_options();

  if (!router_have_minimum_dir_info()) {
    int quiet = directory_too_idle_to_fetch_descriptors(options, now);
    log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
        "I learned some more directory information, but not enough to "
        "build a circuit: %s", get_dir_info_status_string());
    update_all_descriptor_downloads(now);
    return;
  } else {
    if (directory_fetches_from_authorities(options)) {
      update_all_descriptor_downloads(now);
    }

    /* if we have enough dir info, then update our guard status with
     * whatever we just learned. */
    entry_guards_compute_status(options, now);
    /* Don't even bother trying to get extrainfo until the rest of our
     * directory info is up-to-date */
    if (options->DownloadExtraInfo)
      update_extrainfo_downloads(now);
  }

  if (server_mode(options) && !net_is_disabled() && !from_cache &&
      (can_complete_circuit || !any_predicted_circuits(now)))
    consider_testing_reachability(1, 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dns_servers_relaunch_checks ( void  )

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

Definition at line 1766 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

uint64_t get_bytes_read ( void  )

Provides the traffic read and written over the life of the process.

Definition at line 443 of file main.c.

{
  return stats_n_bytes_read;
}

Here is the caller graph for this function:

uint64_t get_bytes_written ( void  )

Definition at line 450 of file main.c.

Here is the caller graph for this function:

Set *array to an array of all connections, and *n to the length of the array.

*array and *n must not be modified.

Definition at line 433 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

unsigned get_signewnym_epoch ( void  )

Return the number of times that signewnym has been called.

Definition at line 1124 of file main.c.

{
  return newnym_epoch;
}

Here is the caller graph for this function:

long get_uptime ( void  )

Returns Tor's uptime.

Definition at line 2073 of file main.c.

Here is the caller graph for this function:

void handle_signals ( int  is_parent)

Set up the signal handlers for either parent or child.

Definition at line 2213 of file main.c.

{
#ifndef _WIN32 /* do signal stuff only on Unix */
  int i;
  static const int signals[] = {
    SIGINT,  /* do a controlled slow shutdown */
    SIGTERM, /* to terminate now */
    SIGPIPE, /* otherwise SIGPIPE kills us */
    SIGUSR1, /* dump stats */
    SIGUSR2, /* go to loglevel debug */
    SIGHUP,  /* to reload config, retry conns, etc */
#ifdef SIGXFSZ
    SIGXFSZ, /* handle file-too-big resource exhaustion */
#endif
    SIGCHLD, /* handle dns/cpu workers that exit */
    -1 };
  static struct event *signal_events[16]; /* bigger than it has to be. */
  if (is_parent) {
    for (i = 0; signals[i] >= 0; ++i) {
      signal_events[i] = tor_evsignal_new(
                       tor_libevent_get_base(), signals[i], signal_callback,
                       (void*)(uintptr_t)signals[i]);
      if (event_add(signal_events[i], NULL))
        log_warn(LD_BUG, "Error from libevent when adding event for signal %d",
                 signals[i]);
    }
  } else {
    struct sigaction action;
    action.sa_flags = 0;
    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_IGN;
    sigaction(SIGINT,  &action, NULL);
    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGPIPE, &action, NULL);
    sigaction(SIGUSR1, &action, NULL);
    sigaction(SIGUSR2, &action, NULL);
    sigaction(SIGHUP,  &action, NULL);
#ifdef SIGXFSZ
    sigaction(SIGXFSZ, &action, NULL);
#endif
  }
#else /* MS windows */
  (void)is_parent;
#endif /* signal stuff */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int have_lockfile ( void  )

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

Definition at line 2401 of file main.c.

{
  return lockfile != NULL;
}

Here is the caller graph for this function:

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.

Definition at line 1740 of file main.c.

{
  int server = server_mode(get_options());

  if (at_interface) {
    if (! server) {
      /* Okay, change our keys. */
      if (init_keys()<0)
        log_warn(LD_GENERAL, "Unable to rotate keys after IP change!");
    }
  } else {
    if (server) {
      if (stats_n_seconds_working > UPTIME_CUTOFF_FOR_NEW_BANDWIDTH_TEST)
        reset_bandwidth_test();
      stats_n_seconds_working = 0;
      router_reset_reachability();
      mark_my_descriptor_dirty("IP address changed");
    }
  }

  dns_servers_relaunch_checks();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void process_signal ( uintptr_t  sig)

Do the work of acting on a signal received in sig

Definition at line 2005 of file main.c.

{
  switch (sig)
    {
    case SIGTERM:
      log_notice(LD_GENERAL,"Catching signal TERM, exiting cleanly.");
      tor_cleanup();
      exit(0);
      break;
    case SIGINT:
      if (!server_mode(get_options())) { /* do it now */
        log_notice(LD_GENERAL,"Interrupt: exiting cleanly.");
        tor_cleanup();
        exit(0);
      }
      hibernate_begin_shutdown();
      break;
#ifdef SIGPIPE
    case SIGPIPE:
      log_debug(LD_GENERAL,"Caught SIGPIPE. Ignoring.");
      break;
#endif
    case SIGUSR1:
      /* prefer to log it at INFO, but make sure we always see it */
      dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
      control_event_signal(sig);
      break;
    case SIGUSR2:
      switch_logs_debug();
      log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
                "Send HUP to change back.");
      control_event_signal(sig);
      break;
    case SIGHUP:
      if (do_hup() < 0) {
        log_warn(LD_CONFIG,"Restart failed (config error?). Exiting.");
        tor_cleanup();
        exit(1);
      }
      control_event_signal(sig);
      break;
#ifdef SIGCHLD
    case SIGCHLD:
      while (waitpid(-1,NULL,WNOHANG) > 0) ; /* keep reaping until no more
                                                zombies */
      break;
#endif
    case SIGNEWNYM: {
      time_t now = time(NULL);
      if (time_of_last_signewnym + MAX_SIGNEWNYM_RATE > now) {
        signewnym_is_pending = 1;
        log(LOG_NOTICE, LD_CONTROL,
            "Rate limiting NEWNYM request: delaying by %d second(s)",
            (int)(MAX_SIGNEWNYM_RATE+time_of_last_signewnym-now));
      } else {
        signewnym_impl(now);
      }
      break;
    }
    case SIGCLEARDNSCACHE:
      addressmap_clear_transient();
      control_event_signal(sig);
      break;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void release_lockfile ( void  )

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

Definition at line 2408 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_cleanup ( void  )

Do whatever cleanup is necessary before shutting Tor down.

Definition at line 2478 of file main.c.

{
  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. */
    if (options->PidFile)
      unlink(options->PidFile);
    if (options->ControlPortWriteToFile)
      unlink(options->ControlPortWriteToFile);
    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_tests_reachability(options))
      rep_hist_record_mtbf_data(now, 0);
  }
#ifdef USE_DMALLOC
  dmalloc_log_stats();
#endif
  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. */
  crypto_global_cleanup();
#ifdef USE_DMALLOC
  dmalloc_log_unfreed();
  dmalloc_shutdown();
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

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).

Definition at line 2425 of file main.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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

Main entry point for the Tor process.

Called from main().

Definition at line 2586 of file main.c.

{
  int result = 0;
#if defined (WINCE)
  WCHAR path [MAX_PATH] = {0};
  WCHAR fullpath [MAX_PATH] = {0};
  PWCHAR p = NULL;
  FILE* redir = NULL;
  FILE* redirdbg = NULL;

  // this is to facilitate debugging by opening
  // a file on a folder shared by the wm emulator.
  // if no flashcard (real or emulated) is present,
  // log files will be written in the root folder
  if (find_flashcard_path(path,MAX_PATH) == -1) {
    redir = _wfreopen( L"\\stdout.log", L"w", stdout );
    redirdbg = _wfreopen( L"\\stderr.log", L"w", stderr );
  } else {
    swprintf(fullpath,L"\\%s\\tor",path);
    CreateDirectory(fullpath,NULL);

    swprintf(fullpath,L"\\%s\\tor\\stdout.log",path);
    redir = _wfreopen( fullpath, L"w", stdout );

    swprintf(fullpath,L"\\%s\\tor\\stderr.log",path);
    redirdbg = _wfreopen( fullpath, L"w", stderr );
  }
#endif

#ifdef _WIN32
  /* Call SetProcessDEPPolicy to permanently enable DEP.
     The function will not resolve on earlier versions of Windows,
     and failure is not dangerous. */
  HMODULE hMod = GetModuleHandleA("Kernel32.dll");
  if (hMod) {
    typedef BOOL (WINAPI *PSETDEP)(DWORD);
    PSETDEP setdeppolicy = (PSETDEP)GetProcAddress(hMod,
                           "SetProcessDEPPolicy");
    if (setdeppolicy) setdeppolicy(1); /* PROCESS_DEP_ENABLE */
  }
#endif

  update_approx_time(time(NULL));
  tor_threads_init();
  init_logging();
#ifdef USE_DMALLOC
  {
    /* Instruct OpenSSL to use our internal wrappers for malloc,
       realloc and free. */
    int r = CRYPTO_set_mem_ex_functions(_tor_malloc, _tor_realloc, _tor_free);
    tor_assert(r);
  }
#endif
#ifdef NT_SERVICE
  {
     int done = 0;
     result = nt_service_parse_options(argc, argv, &done);
     if (done) return result;
  }
#endif
  if (tor_init(argc, argv)<0)
    return -1;
  switch (get_options()->command) {
  case CMD_RUN_TOR:
#ifdef NT_SERVICE
    nt_service_set_state(SERVICE_RUNNING);
#endif
    result = do_main_loop();
    break;
  case CMD_LIST_FINGERPRINT:
    result = do_list_fingerprint();
    break;
  case CMD_HASH_PASSWORD:
    do_hash_password();
    result = 0;
    break;
  case CMD_VERIFY_CONFIG:
    printf("Configuration was valid\n");
    result = 0;
    break;
  case CMD_RUN_UNITTESTS: /* only set by test.c */
  default:
    log_warn(LD_BUG,"Illegal command number %d: internal error.",
             get_options()->command);
    result = -1;
  }
  tor_cleanup();
  return result;
}
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.

Definition at line 2365 of file main.c.

{
  if (lockfile)
    return 0;
  else {
    char *fname = options_get_datadir_fname2_suffix(options, "lock",NULL,NULL);
    int already_locked = 0;
    tor_lockfile_t *lf = tor_lockfile_lock(fname, 0, &already_locked);
    tor_free(fname);
    if (!lf) {
      if (err_if_locked && already_locked) {
        int r;
        log_warn(LD_GENERAL, "It looks like another Tor process is running "
                 "with the same data directory.  Waiting 5 seconds to see "
                 "if it goes away.");
#ifndef _WIN32
        sleep(5);
#else
        Sleep(5000);
#endif
        r = try_locking(options, 0);
        if (r<0) {
          log_err(LD_GENERAL, "No, it's still there.  Exiting.");
          exit(0);
        }
        return r;
      }
      return -1;
    }
    lockfile = lf;
    return 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

We set this to 1 when we've opened a circuit, so we can print a log entry to inform the user that Tor is working.

We set it to 0 when we think the fact that we once opened a circuit doesn't mean we can do so any longer (a big time jump happened, when we notice our directory is heinously out-of-date, etc.

Definition at line 142 of file main.c.