Exemplo n.º 1
0
/**
 * Entry point for main thread to enter the networking
 * stack. This method blocks indefinitely until the
 * network stack is shutdown.
 * @arg netconf The configuration for the networking stack.
 * @arg should_run A reference to a variable that is set to 0 when
 * shutdown should be started
 */
void enter_networking_loop(statsite_networking *netconf, int *should_run) {
    // Allocate our user data
    worker_ev_userdata data;
    data.netconf = netconf;

    // Set the user data to be for this thread
    ev_set_userdata(&data);

    // Run forever until we are told to halt
    while (likely(*should_run)) {
        ev_run(EVRUN_ONCE);
    }
    return;
}
Exemplo n.º 2
0
Arquivo: core.c Projeto: mobius/libuv
static int uv__loop_init(uv_loop_t* loop,
                         struct ev_loop *(ev_loop_new)(unsigned int flags)) {
  memset(loop, 0, sizeof(*loop));
  RB_INIT(&loop->uv_ares_handles_);
#if HAVE_KQUEUE
  loop->ev = ev_loop_new(EVBACKEND_KQUEUE);
#else
  loop->ev = ev_loop_new(EVFLAG_AUTO);
#endif
  ev_set_userdata(loop->ev, loop);
  eio_channel_init(&loop->uv_eio_channel, loop);
  uv__loop_platform_init(loop);
  return 0;
}
Exemplo n.º 3
0
bool Redox::initEv() {
  signal(SIGPIPE, SIG_IGN);
  evloop_ = ev_loop_new(EVFLAG_AUTO);
  if (evloop_ == nullptr) {
    logger_.fatal() << "Could not create a libev event loop.";
    {
      unique_lock<mutex> lk(connect_lock_);
      connect_state_ = INIT_ERROR;
    }
    connect_waiter_.notify_all();
    return false;
  }
  ev_set_userdata(evloop_, (void *)this); // Back-reference
  return true;
}
static void
dispose_ev_loop (MilterLibevEventLoopPrivate *priv)
{
    dispose_release(priv);
    if (priv->ev_loop) {
        if (priv->breaker) {
            ev_async_stop(priv->ev_loop, priv->breaker);
            g_free(priv->breaker);
            priv->breaker = NULL;
        }
        ev_set_userdata(priv->ev_loop, NULL);
        ev_loop_destroy(priv->ev_loop);
        priv->ev_loop = NULL;
    }
}
Exemplo n.º 5
0
struct packetproc*
packetproc_new(struct dp *dp) {
    struct packetproc *packetproc = malloc(sizeof(struct packetproc));
    packetproc->dp     = dp;
    packetproc->logger = logger_mgr_get(LOGGER_NAME_PP);

    packetproc->pp_map                = NULL;
    packetproc->max_pp_num_global     = MAX_PP_NUM_GLOBAL;
    packetproc->current_pp_num_global = 0;

    packetproc->pp_shared_data = NULL;

    struct packetproc_loop *packetproc_loop = malloc(sizeof(struct packetproc_loop));
    packetproc_loop->dp                     = dp;
    packetproc_loop->logger                 = logger_mgr_get(LOGGER_NAME_PP_LOOP);

    packetproc->packetproc_loop = packetproc_loop;
    packetproc_loop->packetproc = packetproc;

    packetproc->thread    = malloc(sizeof(pthread_t));
    packetproc->loop      = ev_loop_new(0/*flags*/);
    packetproc_loop->loop = packetproc->loop;
    packetproc->msg_mbox   = mbox_new(packetproc->loop, packetproc_loop, process_msg);
    
    packetproc->mutex = malloc(sizeof(pthread_mutex_t));
    pthread_mutex_init(packetproc->mutex, NULL);

    /* Initialize basic packet processor structures and
     * call #ppName#_packetproc_init for every pp type */
    init_packetprocessors(packetproc);

    ev_set_userdata(packetproc->loop, (void *)packetproc_loop);

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int rc;
    if ((rc = pthread_create(packetproc->thread, &attr, event_loop, (void *)packetproc_loop)) != 0) {
        logger_log(packetproc->logger, LOG_ERR, "Unable to create thread (%d).", rc);
        //TODO free structures
        return NULL;
    }

    logger_log(packetproc->logger, LOG_INFO, "Initialized.");

    return packetproc;
}
Exemplo n.º 6
0
flux_reactor_t *flux_reactor_create (int flags)
{
    flux_reactor_t *r = xzmalloc (sizeof (*r));
    if ((flags & FLUX_REACTOR_SIGCHLD))
        r->loop = ev_default_loop (EVFLAG_SIGNALFD);
    else
        r->loop = ev_loop_new (EVFLAG_NOSIGMASK);
    if (!r->loop) {
        errno = ENOMEM;
        flux_reactor_destroy (r);
        return NULL;
    }
    ev_set_userdata (r->loop, r);
    r->usecount = 1;
    return r;
}
Exemplo n.º 7
0
int main(int argc, char *argv[])
{
    if (0 != parse_options(argc, argv))
    {
        usage();
        return 1;
    }

    if (!verbose)
        log_setlevel(LOGLEVEL_CRITICAL);

    memset(&g_srvctx, 0, sizeof(g_srvctx));
    g_srvctx.loop = ev_default_loop(0);
    ev_set_userdata(g_srvctx.loop, &g_srvctx);

    if (NULL == (g_srvctx.timer_1hz = (struct ev_timer *)malloc(sizeof(struct ev_timer))))
        LOG_CRITICAL("out of mem");
    if (NULL == (g_srvctx.timer_10hz = (struct ev_timer *)malloc(sizeof(struct ev_timer))))
        LOG_CRITICAL("out of mem");
    if (NULL == (g_srvctx.idle_watcher = (struct ev_idle *)malloc(sizeof(struct ev_idle))))
        LOG_CRITICAL("out of mem");

    ev_timer_init(g_srvctx.timer_1hz, (void *)timeout_1hz_cb, 0, 1);
    ev_set_priority(g_srvctx.timer_1hz, EV_MAXPRI);
    ev_timer_start(g_srvctx.loop, g_srvctx.timer_1hz);
    ev_timer_init(g_srvctx.timer_10hz, (void *)timeout_10hz_cb, 0, 0.1);
    ev_set_priority(g_srvctx.timer_10hz, EV_MAXPRI);
    ev_timer_start(g_srvctx.loop, g_srvctx.timer_10hz);
    ev_idle_init(g_srvctx.idle_watcher, idle_cb);

    if (0 != serial_init(g_srvctx.loop, &(g_srvctx.serialctx), device_name))
    {
        LOG_CRITICAL("Failed to open %s", device_name);
    }

    if (0 != mqtt_connect(&(g_srvctx.mqttctx), CLIENT_NAME, server, port))
    {
        LOG_CRITICAL("failed to connect to server");
    }

    while(1)
    {
        ev_loop(g_srvctx.loop, 0);
    }

    return 0;
}
Exemplo n.º 8
0
int
main (int argc, char *argv[])
{
    struct sockaddr_in sin;
    struct S5srv_t root;
    int lv;
    ev_io *eve;
#if EV_MULTIPLICITY
    struct ev_loop *loop = EV_DEFAULT;
    if (!loop)
    {
        fprintf (stderr, "can't init libev\n");
        return EXIT_FAILURE;
    }
#endif
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr ("0.0.0.0");
    sin.sin_port = htons ((unsigned short)1080);
    fprintf (stderr, "socket () S5s\n");
    root.fd = socket (AF_INET, SOCK_STREAM, 0);
    fprintf (stderr, "bind () S5s\n");
    lv = bind (root.fd, (struct sockaddr*)&sin, sizeof (struct sockaddr_in));
    if (lv == -1)
    {
        perror ("bind");
        return EXIT_FAILURE;
    }
    fprintf (stderr, "listen () S5s\n");
    lv = listen (root.fd, 1);
    if (lv == -1)
    {
        perror ("listen");
        return EXIT_FAILURE;
    }
    fprintf (stderr, "ev_io_init () S5s\n");
    eve = &(root.evio);
    ev_io_init (eve, S5_server_cb, root.fd, EV_READ);
    ev_io_start (EV_A_ eve);
    /* put *root to current ev_loop */
    ev_set_userdata (EV_A_ &root);
    fprintf (stderr, "RUN libev\n");
    ev_run (EV_A_ 0);
    fprintf (stderr, "DESTROY\n");
    /* TODO */
    return EXIT_SUCCESS;
}
Exemplo n.º 9
0
/* Static initializer for the driver. */
struct pcap_drv * MALLOC_ATTR
pcap_drv_init(struct port_drv *drv) {
    struct pcap_drv *pcap_drv = malloc(sizeof(struct pcap_drv));
    pcap_drv->drv = drv;
    pcap_drv->logger = logger_mgr_get(LOGGER_NAME_PORT_DRV_PCAP);

    pcap_drv->ports_map = NULL;
    size_t i;
    for (i=0; i<MAX_PORTS; i++) {
        pcap_drv->ports[i] = NULL;
    }
    pcap_drv->ports_num = 0;

    pcap_drv->ports_rwlock = malloc(sizeof(pthread_rwlock_t));
    pthread_rwlock_init(pcap_drv->ports_rwlock, NULL);

    struct pcap_drv_loop *pcap_drv_loop = malloc(sizeof(struct pcap_drv_loop));
    pcap_drv_loop->logger = logger_mgr_get(LOGGER_NAME_PORT_DRV_PCAP_IF);

    pcap_drv->pcap_drv_loop = pcap_drv_loop;
    pcap_drv_loop->pcap_drv = pcap_drv;

    pcap_drv->thread = malloc(sizeof(pthread_t));
    pcap_drv->loop = ev_loop_new(0/*flags*/);
    pcap_drv_loop->loop = pcap_drv->loop;

    ev_set_userdata(pcap_drv->loop, (void *)pcap_drv_loop);

    pcap_drv->notifier = mbox_new(pcap_drv->loop, NULL, NULL);

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int rc;
    if ((rc = pthread_create(pcap_drv->thread, &attr, event_loop, (void *)pcap_drv_loop)) != 0) {
        logger_log(pcap_drv->logger, LOG_ERR, "Unable to create thread (%d).", rc);
        //TODO: free structures
        return NULL;
    }

    logger_log(pcap_drv->logger, LOG_INFO, "PCAP initialized.");

    return pcap_drv;
}
Exemplo n.º 10
0
/**
 * Entry point for the main thread to start accepting
 * @arg netconf The configuration for the networking stack.
 * @arg should_run A flag checked to see if we should run
 * @arg threads The list of worker threads
 */
void enter_main_loop(bloom_networking *netconf, int *should_run, pthread_t *threads) {
    // Store a reference to the threads
    netconf->threads = threads;

    // Set the user data of the main loop to netconf
    ev_set_userdata(netconf->default_loop, netconf);

    // Syncronize now that netconf->threads are ready
    barrier_wait(&netconf->thread_barrier);

    // Syncronize until threads are registered
    barrier_wait(&netconf->thread_barrier);

    // Run forever
    while (*should_run) {
        ev_run(netconf->default_loop, EVRUN_ONCE);
    }
}
Exemplo n.º 11
0
/* new_loop - instanciate a Loop */
Loop *
new_Loop(PyTypeObject *type, PyObject *args, PyObject *kwargs, char default_loop)
{
    Loop *self;
    unsigned int flags = EVFLAG_AUTO;
    PyObject *callback = Py_None, *data = NULL, *debug = Py_False;
    double io_interval = 0.0, timeout_interval = 0.0;

    static char *kwlist[] = {"flags", "callback", "data", "debug",
                             "io_interval", "timeout_interval", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|IOOO!dd:__new__", kwlist,
            &flags, &callback, &data, &PyBool_Type, &debug,
            &io_interval, &timeout_interval)) {
        return NULL;
    }
    /* self */
    self = (Loop *)type->tp_alloc(type, 0);
    if (!self) {
        return NULL;
    }
    /* self->loop */
    self->loop = default_loop ? ev_default_loop(flags) : ev_loop_new(flags);
    if (!self->loop) {
        PyErr_SetString(Error, "could not create Loop, bad 'flags'?");
        Py_DECREF(self);
        return NULL;
    }
    /* self->callback, self->io_interval, self->timeout_interval */
    if (set_callback_Loop(self, callback) ||
        set_interval_Loop(self, io_interval, 1) ||
        set_interval_Loop(self, timeout_interval, 0)) {
        Py_DECREF(self);
        return NULL;
    }
    /* self->data */
    Py_XINCREF(data);
    self->data = data;
    /* self->debug */
    self->debug = (debug == Py_True) ? 1 : 0;
    /* done */
    ev_set_userdata(self->loop, (void *)self);
    return self;
}
Exemplo n.º 12
0
/* Creates and spawns a new controller handler. */
struct ctrl * MALLOC_ATTR
ctrl_new(struct dp *dp) {
    struct ctrl *ctrl = malloc(sizeof(struct ctrl));
    ctrl->dp = dp;
    ctrl->logger = logger_mgr_get(LOGGER_NAME_CTRL, dp_get_uid(dp));

    struct ctrl_loop *ctrl_loop = malloc(sizeof(struct ctrl_loop));
    ctrl_loop->dp = dp;
    ctrl_loop->logger = logger_mgr_get(LOGGER_NAME_CTRL_IF, dp_get_uid(dp));

    size_t i;
    for (i=0; i<MAX_CONNS; i++) {
        ctrl_loop->conns[i] = NULL;
    }
    ctrl_loop->conns_num = 1; // "0" is used for broadcast

    ctrl->ctrl_loop = ctrl_loop;
    ctrl_loop->ctrl = ctrl;

    ctrl->thread = malloc(sizeof(pthread_t));
    ctrl->loop   = ev_loop_new(0/*flags*/);
    ctrl_loop->loop = ctrl->loop;

    ctrl->cmd_mbox = mbox_new(ctrl->loop, ctrl_loop, process_cmd);
    ctrl->msg_mbox = mbox_new(ctrl->loop, ctrl_loop, process_msg);

    ev_set_userdata(ctrl->loop, (void *)ctrl_loop);

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    int rc;
    if ((rc = pthread_create(ctrl->thread, &attr, event_loop, (void *)ctrl_loop)) != 0) {
        logger_log(ctrl->logger, LOG_ERR, "Unable to create thread (%d).", rc);
        //TODO free structures
        return NULL;
    }

    logger_log(ctrl->logger, LOG_INFO, "Initialized.");

    return ctrl;
}
Exemplo n.º 13
0
void server_run(ServerInfo* server_info)
{
    struct ev_loop* mainloop = ev_loop_new(0);
    ev_set_userdata(mainloop, server_info);

    ev_io accept_watcher;
    ev_io_init(&accept_watcher, ev_io_on_request, server_info->sockfd, EV_READ);
    ev_io_start(mainloop, &accept_watcher);

#if WANT_SIGINT_HANDLING
    ev_signal signal_watcher;
    ev_signal_init(&signal_watcher, ev_signal_on_sigint, SIGINT);
    ev_signal_start(mainloop, &signal_watcher);
#endif

    /* This is the program main loop */
    Py_BEGIN_ALLOW_THREADS
    ev_loop(mainloop, 0);
    ev_default_destroy();
    Py_END_ALLOW_THREADS
}
Exemplo n.º 14
0
int uv__loop_init(uv_loop_t* loop, int default_loop) {
#if HAVE_KQUEUE
  int flags = EVBACKEND_KQUEUE;
#else
  int flags = EVFLAG_AUTO;
#endif
  memset(loop, 0, sizeof(*loop));
  RB_INIT(&loop->uv_ares_handles_);
  loop->endgame_handles = NULL;
  loop->channel = NULL;
  loop->ev = (default_loop ? ev_default_loop : ev_loop_new)(flags);
  ev_set_userdata(loop->ev, loop);
  eio_channel_init(&loop->uv_eio_channel, loop);
#if __linux__
  RB_INIT(&loop->inotify_watchers);
  loop->inotify_fd = -1;
#endif
#if HAVE_PORTS_FS
  loop->fs_fd = -1;
#endif
  return 0;
}
Exemplo n.º 15
0
void TcpServer::IOHandleThread() {
	LogManager::GetLogManager()->Log(
			LOG_MSG,
			"TcpServer::IOHandleThread( [Start] )"
			);

	// 把mServer放到事件监听队列
	ev_io_init(mpAcceptWatcher, accept_handler, mpSocket->fd, EV_READ);
	mpAcceptWatcher->data = mpSocket;
	ev_io_start(mLoop, mpAcceptWatcher);

	// 增加回调参数
	ev_set_userdata(mLoop, this);

	// 执行epoll_wait
	ev_run(mLoop, 0);

	LogManager::GetLogManager()->Log(
			LOG_MSG,
			"TcpServer::IOHandleThread( "
			"[Exit]"
			")"
			);
}
Exemplo n.º 16
0
/**
 * Entry point for threads to join the networking
 * stack. This method blocks indefinitely until the
 * network stack is shutdown.
 * @arg netconf The configuration for the networking stack.
 */
void start_networking_worker(statsite_proxy_networking *netconf) {
    // Allocate our user data
    worker_ev_userdata data;
    data.netconf = netconf;
    netconf->thread = pthread_self();

    // Set the user data to be for this thread
    ev_set_userdata(&data);

    // Run forever until we are told to halt
    while (netconf->should_run) {
        data.watcher = NULL;
        data.ready_events = 0;

        // Run one iteration of the event loop
        ev_run(EVRUN_ONCE);

        // Process the event
        if (data.watcher) {
            invoke_event_handler(&data);
        }
    }
    return;
}
Exemplo n.º 17
0
int main(int argc, char** argv) {
    if (argc < 4) {
        printf("Usage: %s ip port path2worker [shmsize]\n", argv[0]);
        return EXIT_FAILURE;
    }


    struct listener_s listener;
    listener.argc = argc;
    listener.argv = argv;
    listener.stop_moniter = 0;
    listener.shm_id = -1;
    listener.shm_size = -1;

    if (argc > 4) {
        listener.shm_size = atoi(argv[4]);
        if (listener.shm_size > 0) {
            listener.shm_id = shm_alloc(0, listener.shm_size);
        }
        if (listener.shm_id != -1) {
            shm_free(listener.shm_id); // lazy free
        }
    }


    // get loop
    struct ev_loop* loop = ev_default_loop(EVBACKEND_EPOLL);
    ev_set_userdata(loop, &listener);


    // setup signal handler
    struct ev_signal quitwatcher;
    struct ev_signal hupwatcher;
    ev_signal_init(&quitwatcher, listener_stop, SIGQUIT);
    ev_signal_init(&hupwatcher, restart_workers, SIGHUP);
    ev_signal_start(loop, &quitwatcher);
    ev_unref(loop); // 将loop中的watchercnt--,保证不停止此watcher的情况下loop也能正常退出
    ev_signal_start(loop, &hupwatcher);
    ev_unref(loop); // 将loop中的watchercnt--,保证不停止此watcher的情况下loop也能正常退出


    // get cpu number
    listener.worker_count = (int)sysconf(_SC_NPROCESSORS_CONF);


    // init workers
    struct worker_s workers[listener.worker_count];
    listener.workers = &workers[0];

    if (0 != setup_workers(loop, &listener)) {
        return EXIT_FAILURE;
    }


    int r = ev_run(loop, 0);


    ev_ref(loop);
    ev_signal_stop(loop, &quitwatcher);
    ev_ref(loop);
    ev_signal_stop(loop, &hupwatcher);


    return r;
}
Exemplo n.º 18
0
Arquivo: main.c Projeto: akalend/mymc
int main(int argc, char **argv){

	int mc_sock;
	addr_t mc_addr;	
	ev_io  mc_io;
	sophiadb_t * db;		
	int c;	
	
	
	while (1) {
		int option_index = 0;
		static struct option long_options[] = {
			{"help",		no_argument,		0, 'h'},
			{"version",		no_argument,		0, 'V'},
			{"max-clients",	required_argument,	0, 'l'},
			{0, 0, 0, 0}
		};
		c = getopt_long(argc, argv, "n:Vc:t", long_options, &option_index);
		if (c == -1)
			break;
		switch (c) {
			case 'c':
				confilename = optarg;
				break;
			case 'n':
				max_clients = atoi(optarg);
				break;
			case 'V':
				printf("Version %s\n",  MYMC_VERSION);
				exit(0);
			case 't':
				is_trace = 1;
				break;			default:
				usage(argv[0], c == 'h' ? EXIT_SUCCESS : EXIT_FAILURE);
		}
	}
	

	if (confilename) 
		parse(confilename, &server_ctx);
	else	
		parse( CONFIGFILE, &server_ctx);

	//assert(server_ctx.logfile);
	//assert(server_ctx.listen);
	
	if (!server_ctx.listen) {
		perror("undefined listen port");
		exit(1);
	}
	

	flog =  server_ctx.logfile ? fopen(server_ctx.logfile, "a+") : fopen("error.log", "a+");
	
	if (flog) {		
		time_t lt;
  		lt = time(NULL);
  		fprintf(flog, "server started at %s\n",ctime(&lt));	
	}	else {
			perror("can not create log file");
			exit(1);
		}

	daemonize(server_ctx.is_demonize, server_ctx.pidfile, server_ctx.username);

	set_rlimit();	
	ignore_sigpipe();
		
	init_addr(&mc_addr, server_ctx.listen);

	mc_sock = socket(mc_addr.pf_family, SOCK_STREAM, 0);
	if (mc_sock < 0) {
		perror("can't create socket");
		exit(1);
	}

	listen_sock(mc_sock, &mc_addr);
	
	//TODO	
	if (is_trace)
		printf("pid=%ld\n\n", (long)getpid());
	
	clients = calloc(max_clients, sizeof(fd_ctx));
	if (!clients) {
		perror_fatal("Cannot allocate array for client descriptors!");		
	}

	int i=0;
	while(i < max_clients) {
		if(clients[i].mc) 
			printf("init err %i\n", i);
		i++;
	}
		
	db = db_init(&server_ctx);
	assert(db);
	
	struct ev_loop *loop = ev_default_loop(0);	
	assert(loop);
	
	ev_set_userdata(loop,(void*)db);	
		
	ev_io_init(  &mc_io, memcached_on_connect, mc_sock, EV_READ);		
	ev_io_start(loop, &mc_io);

	struct ev_timer timeout_watcher;	

	ev_init(&timeout_watcher, periodic_watcher);
	timeout_watcher.repeat = TIME_CHECK_INTERVAL;
	ev_timer_again(loop, &timeout_watcher);

	struct ev_signal signal_watcher,signal_watcher2;
	
//	ev_signal_init (&signal_watcher, sigint_cb, SIGINT);
//	ev_signal_start (loop,  &signal_watcher);
	
	ev_signal_init (&signal_watcher, sigint_cb, SIGTERM);
	ev_signal_start (loop,  &signal_watcher);

	ev_signal_init (&signal_watcher2, sighup_cb, SIGHUP);
	ev_signal_start (loop,  &signal_watcher2);
	

	//start server
	time(&stats.uptime);
	gettimeofday(&t_start, NULL);

	// event loop
	ev_loop(loop, 0);
	
	cllear_mc_all();	
	close(mc_sock);	
	
	if (clients) 
		free(clients);
	
	//ev_loop_destroy(loop);
	
	destroy(db);
	
	if (mc_addr.a_addr) free(mc_addr.a_addr);
	
	if (server_ctx.pidfile) {		
		if( unlink(server_ctx.pidfile))
			printf("cannot delete pid file %s %s\n",server_ctx.pidfile, strerror(errno));
	}	

	free_config(); 
	if (flog) {		
		time_t lt;
  		lt = time(NULL);
  		
  		fprintf(flog, "server finis Ok at %s\n",ctime(&lt));
		fclose(flog);	
	}

	return 0;
	 
}
Exemplo n.º 19
0
uv_loop_t* uv_loop_new(void) {
  uv_loop_t* loop = calloc(1, sizeof(uv_loop_t));
  loop->ev = ev_loop_new(0);
  ev_set_userdata(loop->ev, loop);
  return loop;
}
Exemplo n.º 20
0
/**
 * Entry point for threads to join the networking
 * stack. This method blocks indefinitely until the
 * network stack is shutdown.
 * @arg netconf The configuration for the networking stack.
 */
void start_networking_worker(hlld_networking *netconf) {
    // Allocate our user data
    worker_ev_userdata data;
    data.netconf = netconf;
    data.should_run = 1;
    data.inactive = NULL;

    // Allocate our pipe
    if (pipe(data.pipefd)) {
        perror("failed to allocate worker pipes!");
        return;
    }

    // Create the event loop
    if (!(data.loop = ev_loop_new(netconf->ev_mode))) {
        syslog(LOG_ERR, "Failed to create event loop for worker!");
        return;
    }

    // Set the user data to be for this thread
    ev_set_userdata(data.loop, &data);

    // Setup the pipe listener
    ev_io_init(&data.pipe_client, handle_worker_notification,
                data.pipefd[0], EV_READ);
    ev_io_start(data.loop, &data.pipe_client);

    // Setup the periodic timers,
    ev_timer_init(&data.periodic, handle_periodic_timeout,
                PERIODIC_TIME_SEC, 1);
    ev_timer_start(data.loop, &data.periodic);

    // Syncronize until netconf->threads is available
    barrier_wait(&netconf->thread_barrier);

    // Register this thread so we can accept connections
    assert(netconf->threads);
    pthread_t id = pthread_self();
    for (int i=0; i < netconf->config->worker_threads; i++) {
        if (pthread_equal(id, netconf->threads[i])) {
            // Provide a pointer to our data
            netconf->workers[i] = &data;
            break;
        }
    }

    // Wait for everybody to be registered
    barrier_wait(&netconf->thread_barrier);

    // Run the event loop
    while (data.should_run) {
        ev_run(data.loop, EVRUN_ONCE);

        // Free inactive connections
        conn_info *c=data.inactive;
        while (c) {
            conn_info *n = c->next;
            close_client_connection(c);
            c = n;
        }
        data.inactive = NULL;
    }

    // Cleanup after exit
    ev_timer_stop(data.loop, &data.periodic);
    ev_io_stop(data.loop, &data.pipe_client);
    close(data.pipefd[0]);
    close(data.pipefd[1]);
    ev_loop_destroy(data.loop);
}