Example #1
0
static void
test_procmon_tor_process_monitor_new(void *ignored)
{
  (void)ignored;
  tor_process_monitor_t *res;
  const char *msg;

  res = tor_process_monitor_new(NULL, "probably invalid", 0, NULL, NULL, &msg);
  tt_assert(!res);
  tt_str_op(msg, OP_EQ, "invalid PID");

  res = tor_process_monitor_new(NULL, "243443535345454", 0, NULL, NULL, &msg);
  tt_assert(!res);
  tt_str_op(msg, OP_EQ, "invalid PID");

  res = tor_process_monitor_new(tor_libevent_get_base(), "43", 0, NULL, NULL, &msg);
  tt_assert(res);
  tt_assert(!msg);

  res = tor_process_monitor_new(tor_libevent_get_base(), "44 hello", 0, NULL, NULL, &msg);
  tt_assert(res);
  tt_assert(!msg);

  res = tor_process_monitor_new(tor_libevent_get_base(), "45:hello", 0, NULL, NULL, &msg);
  tt_assert(res);
  tt_assert(!msg);

 done:
  (void)0;
}
Example #2
0
static int
add_n_work_items(threadpool_t *tp, int n)
{
  int n_queued = 0;
  int n_try_cancel = 0, i;
  workqueue_entry_t **to_cancel;
  workqueue_entry_t *ent;

  to_cancel = tor_malloc(sizeof(workqueue_entry_t*) * opt_n_cancel);

  while (n_queued++ < n) {
    ent = add_work(tp);
    if (! ent) {
      tor_event_base_loopexit(tor_libevent_get_base(), NULL);
      return -1;
    }
    if (n_try_cancel < opt_n_cancel &&
        tor_weak_random_range(&weak_rng, n) < opt_n_cancel) {
      to_cancel[n_try_cancel++] = ent;
    }
  }

  for (i = 0; i < n_try_cancel; ++i) {
    void *work = workqueue_entry_cancel(to_cancel[i]);
    if (! work) {
      n_failed_cancel++;
    } else {
      n_successful_cancel++;
      tor_free(work);
    }
  }

  tor_free(to_cancel);
  return 0;
}
Example #3
0
static void
replysock_readable_cb(tor_socket_t sock, short what, void *arg)
{
  threadpool_t *tp = arg;
  replyqueue_t *rq = threadpool_get_replyqueue(tp);

  int old_r = n_received;
  (void) sock;
  (void) what;

  replyqueue_process(rq);
  if (old_r == n_received)
    return;

  if (opt_verbose) {
    printf("%d / %d", n_received, n_sent);
    if (opt_n_cancel)
      printf(" (%d cancelled, %d uncancellable)",
             n_successful_cancel, n_failed_cancel);
    puts("");
  }
#ifdef TRACK_RESPONSES
  tor_mutex_acquire(&bitmap_mutex);
  for (i = 0; i < opt_n_items; ++i) {
    if (bitarray_is_set(received, i))
      putc('o', stdout);
    else if (bitarray_is_set(handled, i))
      putc('!', stdout);
    else
      putc('.', stdout);
  }
  puts("");
  tor_mutex_release(&bitmap_mutex);
#endif

  if (n_sent - (n_received+n_successful_cancel) < opt_n_lowwater) {
    int n_to_send = n_received + opt_n_inflight - n_sent;
    if (n_to_send > opt_n_items - n_sent)
      n_to_send = opt_n_items - n_sent;
    add_n_work_items(tp, n_to_send);
  }

  if (shutting_down == 0 &&
      n_received+n_successful_cancel == n_sent &&
      n_sent >= opt_n_items) {
    shutting_down = 1;
    threadpool_queue_update(tp, NULL,
                             workqueue_do_shutdown, NULL, NULL);
    // Anything we add after starting the shutdown must not be executed.
    threadpool_queue_work(tp, workqueue_shutdown_error,
                          handle_reply_shutdown, NULL);
    {
      struct timeval limit = { 2, 0 };
      tor_event_base_loopexit(tor_libevent_get_base(), &limit);
    }
  }
}
Example #4
0
/** Work-alike replacement for event_new() on pre-Libevent-2.0 systems. */
struct event *
tor_event_new(struct event_base *base, int sock, short what,
              void (*cb)(int, short, void *), void *arg)
{
  struct event *e = tor_malloc_zero(sizeof(struct event));
  event_set(e, sock, what, cb, arg);
  if (! base)
    base = tor_libevent_get_base();
  event_base_set(base, e);
  return e;
}
Example #5
0
/** Initialize the common timeout that we'll use to refill the buckets every
 * time a tick elapses. */
static void
tor_libevent_set_tick_timeout(int msec_per_tick)
{
  struct event_base *base = tor_libevent_get_base();
  struct timeval tv;

  tor_assert(! one_tick);
  tv.tv_sec = msec_per_tick / 1000;
  tv.tv_usec = (msec_per_tick % 1000) * 1000;
  one_tick = event_base_init_common_timeout(base, &tv);
}
Example #6
0
/** Initializes the libevent backend for a periodic event. */
void
periodic_event_setup(periodic_event_item_t *event)
{
  if (event->ev) { /* Already setup? This is a bug */
    log_err(LD_BUG, "Initial dispatch should only be done once.");
    tor_assert(0);
  }

  event->ev = tor_event_new(tor_libevent_get_base(),
                            -1, 0,
                            periodic_event_dispatch,
                            event);
  tor_assert(event->ev);
}
Example #7
0
/** Handles service control requests, such as stopping or starting the
 * Tor service. */
static void
nt_service_control(DWORD request)
{
  static struct timeval exit_now;
  exit_now.tv_sec  = 0;
  exit_now.tv_usec = 0;

  nt_service_loadlibrary();

  switch (request) {
    case SERVICE_CONTROL_STOP:
        case SERVICE_CONTROL_SHUTDOWN:
          log_notice(LD_GENERAL,
                     "Got stop/shutdown request; shutting down cleanly.");
          service_status.dwCurrentState = SERVICE_STOP_PENDING;
          event_base_loopexit(tor_libevent_get_base(), &exit_now);
          return;
  }
  service_fns.SetServiceStatus_fn(hStatus, &service_status);
}
Example #8
0
static void
timer_cb(tor_timer_t *t, void *arg, const monotime_t *now_mono)
{
  struct timeval now;

  tor_gettimeofday(&now);
  tor_timer_t **t_ptr = arg;
  tor_assert(*t_ptr == t);
  int idx = (int) (t_ptr - timers);
  ++fired[idx];
  timersub(&now, &fire_at[idx], &difference[idx]);
  diffs_mono_usec[idx] =
    monotime_diff_usec(&started_at, now_mono) -
    delay_usec[idx];
  ++n_fired;

  // printf("%d / %d\n",n_fired, N_TIMERS);
  if (n_fired == n_active_timers) {
    tor_libevent_exit_loop_after_callback(tor_libevent_get_base());
  }
}
Example #9
0
/**
 * Initialize the timers subsystem.  Requires that libevent has already been
 * initialized.
 */
void
timers_initialize(void)
{
  if (BUG(global_timeouts))
    return; // LCOV_EXCL_LINE

  timeout_error_t err;
  global_timeouts = timeouts_open(0, &err);
  if (!global_timeouts) {
    // LCOV_EXCL_START -- this can only fail on malloc failure.
    log_err(LD_BUG, "Unable to open timer backend: %s", strerror(err));
    tor_assert(0);
    // LCOV_EXCL_STOP
  }

  struct event *timer_event;
  timer_event = tor_event_new(tor_libevent_get_base(),
                              -1, 0, libevent_timer_callback, NULL);
  tor_assert(timer_event);
  global_timer_event = timer_event;

  libevent_timer_reschedule();
}
Example #10
0
/** This function sets the file descriptor in the <b>handle</b> as non-blocking
 * and configures the libevent event structure based on the given <b>flags</b>
 * to ensure that <b>callback</b> is called whenever we have events on the
 * given <b>handle</b>. */
STATIC void
process_unix_setup_handle(process_t *process,
                          process_unix_handle_t *handle,
                          short flags,
                          event_callback_fn callback)
{
  tor_assert(process);
  tor_assert(handle);
  tor_assert(callback);

  /* Put our file descriptor into non-blocking mode. */
  if (fcntl(handle->fd, F_SETFL, O_NONBLOCK) < 0) {
    log_warn(LD_PROCESS, "Unable mark Unix handle as non-blocking: %s",
             strerror(errno));
  }

  /* Setup libevent event. */
  handle->event = tor_event_new(tor_libevent_get_base(),
                                handle->fd,
                                flags,
                                callback,
                                process);
}
Example #11
0
/*
 * normally tor calls event_base_loopexit so control returns from the libevent
 * event loop back to the tor main loop. tor then activates "linked" socket
 * connections before returning back to the libevent event loop.
 *
 * we hijack and use the libevent loop in nonblock mode, so when tor calls
 * the loopexit, we basically just need to do the linked connection activation.
 * that is extracted to scalliontor_loopexitCallback, which we need to execute
 * as a callback so we don't invoke event_base_loop while it is currently being
 * executed. */
static void scalliontor_loopexitCallback(ScallionTor* stor) {
	update_approx_time(time(NULL));

	scalliontor_notify(stor);

	while(1) {
		/* All active linked conns should get their read events activated. */
		SMARTLIST_FOREACH(active_linked_connection_lst, connection_t *, conn,
				event_active(conn->read_event, EV_READ, 1));

		/* if linked conns are still active, enter libevent loop using EVLOOP_ONCE */
		called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0;
		if(called_loop_once) {
			event_base_loop(tor_libevent_get_base(), EVLOOP_ONCE|EVLOOP_NONBLOCK);
		} else {
			/* linked conns are done */
			break;
		}
	}

	/* make sure we handle any new events caused by the linked conns */
	scalliontor_notify(stor);
}
Example #12
0
void scalliontor_newCPUWorker(ScallionTor* stor, int fd) {
	g_assert(stor);
	if(stor->cpuw) {
		g_free(stor->cpuw);
	}

	vtor_cpuworker_tp cpuw = calloc(1, sizeof(vtor_cpuworker_t));

	cpuw->fd = fd;
	cpuw->state = CPUW_NONE;
#ifdef SCALLION_USEV2CPUWORKER
	cpuw->magic1 = SCALLION_CPUWORKER_MAGIC1;
	cpuw->magic2 = SCALLION_CPUWORKER_MAGIC2;
	cpuw->magic3 = SCALLION_CPUWORKER_MAGIC3;

	setup_server_onion_keys(&(cpuw->onion_keys));
#else
	dup_onion_keys(&(cpuw->onion_key), &(cpuw->last_onion_key));
#endif

	/* setup event so we will get a callback */
	event_assign(&(cpuw->read_event), tor_libevent_get_base(), cpuw->fd, EV_READ|EV_PERSIST, scalliontor_readCPUWorkerCallback, cpuw);
	event_add(&(cpuw->read_event), NULL);
}
Example #13
0
int
main(int argc, char **argv)
{
  replyqueue_t *rq;
  threadpool_t *tp;
  int i;
  tor_libevent_cfg evcfg;
  struct event *ev;
  uint32_t as_flags = 0;

  for (i = 1; i < argc; ++i) {
    if (!strcmp(argv[i], "-v")) {
      opt_verbose = 1;
    } else if (!strcmp(argv[i], "-T") && i+1<argc) {
      opt_n_threads = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "-N") && i+1<argc) {
      opt_n_items = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "-I") && i+1<argc) {
      opt_n_inflight = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "-L") && i+1<argc) {
      opt_n_lowwater = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "-R") && i+1<argc) {
      opt_ratio_rsa = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "-C") && i+1<argc) {
      opt_n_cancel = atoi(argv[++i]);
    } else if (!strcmp(argv[i], "--no-eventfd2")) {
      as_flags |= ASOCKS_NOEVENTFD2;
    } else if (!strcmp(argv[i], "--no-eventfd")) {
      as_flags |= ASOCKS_NOEVENTFD;
    } else if (!strcmp(argv[i], "--no-pipe2")) {
      as_flags |= ASOCKS_NOPIPE2;
    } else if (!strcmp(argv[i], "--no-pipe")) {
      as_flags |= ASOCKS_NOPIPE;
    } else if (!strcmp(argv[i], "--no-socketpair")) {
      as_flags |= ASOCKS_NOSOCKETPAIR;
    } else if (!strcmp(argv[i], "-h")) {
      help();
      return 0;
    } else {
      help();
      return 1;
    }
  }
  if (opt_n_threads < 1 ||
      opt_n_items < 1 || opt_n_inflight < 1 || opt_n_lowwater < 0 ||
      opt_n_cancel > opt_n_inflight || opt_n_inflight > MAX_INFLIGHT ||
      opt_ratio_rsa < 0) {
    help();
    return 1;
  }

  init_logging(1);
  crypto_global_init(1, NULL, NULL);
  crypto_seed_rng(1);

  rq = replyqueue_new(as_flags);
  tor_assert(rq);
  tp = threadpool_new(opt_n_threads,
                      rq, new_state, free_state, NULL);
  tor_assert(tp);

  crypto_seed_weak_rng(&weak_rng);

  memset(&evcfg, 0, sizeof(evcfg));
  tor_libevent_initialize(&evcfg);

  ev = tor_event_new(tor_libevent_get_base(),
                     replyqueue_get_socket(rq), EV_READ|EV_PERSIST,
                     replysock_readable_cb, tp);

  event_add(ev, NULL);

#ifdef TRACK_RESPONSES
  handled = bitarray_init_zero(opt_n_items);
  received = bitarray_init_zero(opt_n_items);
  tor_mutex_init(&bitmap_mutex);
  handled_len = opt_n_items;
#endif

  for (i = 0; i < opt_n_inflight; ++i) {
    if (! add_work(tp)) {
      puts("Couldn't add work.");
      return 1;
    }
  }

  {
    struct timeval limit = { 30, 0 };
    tor_event_base_loopexit(tor_libevent_get_base(), &limit);
  }

  event_base_loop(tor_libevent_get_base(), 0);

  if (n_sent != opt_n_items || n_received+n_successful_cancel != n_sent) {
    printf("%d vs %d\n", n_sent, opt_n_items);
    printf("%d+%d vs %d\n", n_received, n_successful_cancel, n_sent);
    puts("FAIL");
    return 1;
  } else {
    puts("OK");
    return 0;
  }
}
Example #14
0
int
main(int argc, char **argv)
{
  (void)argc;
  (void)argv;
  tor_libevent_cfg cfg;
  memset(&cfg, 0, sizeof(cfg));
  tor_libevent_initialize(&cfg);
  timers_initialize();

  int i;
  int ret;
  struct timeval now;
  tor_gettimeofday(&now);
  monotime_get(&started_at);
  for (i = 0; i < N_TIMERS; ++i) {
    struct timeval delay;
    delay.tv_sec = crypto_rand_int_range(0,MAX_DURATION);
    delay.tv_usec = crypto_rand_int_range(0,1000000);
    delay_usec[i] = delay.tv_sec * 1000000 + delay.tv_usec;
    timeradd(&now, &delay, &fire_at[i]);
    timers[i] = timer_new(timer_cb, &timers[i]);
    timer_schedule(timers[i], &delay);
    ++n_active_timers;
  }

  /* Disable some; we'll make sure they don't trigger. */
  for (i = 0; i < N_DISABLE; ++i) {
    int idx = crypto_rand_int_range(0, N_TIMERS);
    if (is_disabled[idx])
      continue;
    is_disabled[idx] = 1;
    timer_disable(timers[idx]);
    --n_active_timers;
  }

  tor_libevent_run_event_loop(tor_libevent_get_base(), 0);

  int64_t total_difference = 0;
  uint64_t total_square_difference = 0;
  tor_assert(n_fired == n_active_timers);
  for (i = 0; i < N_TIMERS; ++i) {
    if (is_disabled[i]) {
      tor_assert(fired[i] == 0);
      continue;
    }
    tor_assert(fired[i] == 1);
    //int64_t diff = difference[i].tv_usec + difference[i].tv_sec * 1000000;
    int64_t diff = diffs_mono_usec[i];
    total_difference += diff;
    total_square_difference += diff*diff;
  }
  const int64_t mean_diff = total_difference / n_active_timers;
  printf("mean difference: "I64_FORMAT" usec\n",
         I64_PRINTF_ARG(mean_diff));

  const double mean_sq = ((double)total_square_difference)/ n_active_timers;
  const double sq_mean = mean_diff * mean_diff;
  const double stddev = sqrt(mean_sq - sq_mean);
  printf("standard deviation: %lf usec\n", stddev);

#define MAX_DIFF_USEC (500*1000)
#define MAX_STDDEV_USEC (500*1000)
#define ODD_DIFF_USEC (2000)
#define ODD_STDDEV_USEC (2000)

  if (mean_diff < 0 || mean_diff > MAX_DIFF_USEC || stddev > MAX_STDDEV_USEC) {
    printf("Either your system is under ridiculous load, or the "
           "timer backend is broken.\n");
    ret = 1;
  } else if (mean_diff > ODD_DIFF_USEC || stddev > ODD_STDDEV_USEC) {
    printf("Either your system is a bit slow or the "
           "timer backend is odd.\n");
    ret = 0;
  } else {
    printf("Looks good enough.\n");
    ret = 0;
  }

  timer_free_(NULL);

  for (i = 0; i < N_TIMERS; ++i) {
    timer_free(timers[i]);
  }
  timers_shutdown();
  return ret;
}
Example #15
0
void scalliontor_notify(ScallionTor* stor) {
	update_approx_time(time(NULL));

	/* tell libevent to check epoll and activate the ready sockets without blocking */
	event_base_loop(tor_libevent_get_base(), EVLOOP_NONBLOCK);
}