/** 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); }
/** * 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(); }
/** 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); }
/** Create and schedule a new timer that will run every <b>tv</b> in * the event loop of <b>base</b>. When the timer fires, it will * run the timer in <b>cb</b> with the user-supplied data in <b>data</b>. */ periodic_timer_t * periodic_timer_new(struct event_base *base, const struct timeval *tv, void (*cb)(periodic_timer_t *timer, void *data), void *data) { periodic_timer_t *timer; tor_assert(base); tor_assert(tv); tor_assert(cb); timer = tor_malloc_zero(sizeof(periodic_timer_t)); if (!(timer->ev = tor_event_new(base, -1, PERIODIC_FLAGS, periodic_timer_cb, timer))) { tor_free(timer); return NULL; } timer->cb = cb; timer->data = data; #ifndef HAVE_PERIODIC memcpy(&timer->tv, tv, sizeof(struct timeval)); #endif event_add(timer->ev, (struct timeval *)tv); /*drop const for old libevent*/ return timer; }
/** Create a process-termination monitor for the process specifier * given in <b>process_spec</b>. Return a newly allocated * tor_process_monitor_t on success; return NULL and store an error * message into *<b>msg</b> on failure. The caller must not free * the returned error message. * * When the monitored process terminates, call * <b>cb</b>(<b>cb_arg</b>). */ tor_process_monitor_t * tor_process_monitor_new(struct event_base *base, const char *process_spec, log_domain_mask_t log_domain, tor_procmon_callback_t cb, void *cb_arg, const char **msg) { tor_process_monitor_t *procmon = tor_malloc(sizeof(tor_process_monitor_t)); struct parsed_process_specifier_t ppspec; tor_assert(msg != NULL); *msg = NULL; if (procmon == NULL) { *msg = "out of memory"; goto err; } procmon->log_domain = log_domain; if (parse_process_specifier(process_spec, &ppspec, msg)) goto err; procmon->pid = ppspec.pid; #ifdef MS_WINDOWS procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, procmon->pid); if (procmon->hproc != NULL) { procmon->poll_hproc = 1; log_info(procmon->log_domain, "Successfully opened handle to process %d; " "monitoring it.", (int)(procmon->pid)); } else { /* If we couldn't get a handle to the process, we'll try again the * first time we poll. */ log_info(procmon->log_domain, "Failed to open handle to process %d; will " "try again later.", (int)(procmon->pid)); } #endif procmon->cb = cb; procmon->cb_arg = cb_arg; #ifdef PROCMON_POLLS procmon->e = tor_event_new(base, -1 /* no FD */, PERIODIC_TIMER_FLAGS, tor_process_monitor_poll_cb, procmon); /* Note: If you port this file to plain Libevent 2, check that * procmon->e is non-NULL. We don't need to here because * tor_evtimer_new never returns NULL. */ evtimer_add(procmon->e, &poll_interval_tv); #else #error OOPS? #endif return procmon; err: tor_process_monitor_free(procmon); return NULL; }
/** Work-alike replacement for evsignal_new() on pre-Libevent-2.0 systems. */ struct event * tor_evsignal_new(struct event_base * base, int sig, void (*cb)(int, short, void *), void *arg) { return tor_event_new(base, sig, EV_SIGNAL|EV_PERSIST, cb, arg); }
/** Work-alike replacement for evtimer_new() on pre-Libevent-2.0 systems. */ struct event * tor_evtimer_new(struct event_base *base, void (*cb)(int, short, void *), void *arg) { return tor_event_new(base, -1, 0, cb, arg); }
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; } }