Exemplo n.º 1
0
Arquivo: rub.c Projeto: github188/Ptl
 /*Program entrance*/
int main(int argc, char** argv)
{

	key_t ipckey = ftok("/",999);
	int shmid = shmget(ipckey,sizeof(struct tag),IPC_CREAT |0660);
	strTag = (struct tag *)shmat(shmid,NULL,0);
	strTag->str = (char *)malloc(10);
	printf("malloc : %lx\n",(unsigned long)strTag->str);
	pid_t pid = fork();

	if(pid == 0)
	{
		create_base();
	}
	if(pid > 0 )
	{
		signal(SIGCHLD,sig_chld);
		struct event_base *base = event_base_new();
		struct timeval tv = {1,0};
		struct event sig;
		struct event sig1;
//		struct event timeout;
//		evtimer_assign(&timeout,base,timerout,&timeout);
//		evtimer_add(&timeout,&tv);
		evsignal_assign(&sig,base,SIGINT,sig_act,(void *)&sig);
		evsignal_add(&sig,NULL);
		evsignal_assign(&sig1,base,SIGUSR1,sig_act2,(void *)base);
		evsignal_add(&sig1,NULL);
		event_base_dispatch(base);
		event_base_free(base);
		shmdt(strTag);
		shmctl(shmid,IPC_RMID,NULL);
	}
	return 0;
}
Exemplo n.º 2
0
void run(char *conf_file) {
  struct running rr;
  struct event *sig1_ev,*sig2_ev,*sig_hup;

  evthread_use_pthreads();
  setup_running(&rr);
  register_interface_types(&rr);
  register_source_types(&rr);
  run_config(&rr,conf_file);
  start_stats_timer(&rr);
  
  ref_release(&(rr.ic_running));

  event_add(sq_consumer(rr.sq),0);
  event_add(si_consumer(rr.si),0);
  sq_release(rr.sq);
  evsignal_add(sig1_ev=evsignal_new(rr.eb,SIGINT,user_quit,&rr),0);
  evsignal_add(sig2_ev=evsignal_new(rr.eb,SIGTERM,user_quit,&rr),0);
  evsignal_add(sig_hup=evsignal_new(rr.eb,SIGHUP,hupev,&rr),0);
  rr.sigkill_timer = event_new(rr.eb,-1,EV_PERSIST,sigkill_self,&rr);
  log_info(("Starting event loop"));
  event_base_loop(rr.eb,0);
  log_info(("Event loop finished"));
  event_del(sig1_ev);
  event_del(sig2_ev);
  event_del(sig_hup);
  event_free(sig1_ev);
  event_free(sig2_ev);
  event_free(sig_hup);
  closedown(&rr);
  log_info(("Bye!"));
  config_finished();
}
Exemplo n.º 3
0
Arquivo: event.c Projeto: kghost/lldpd
static void
levent_init(struct lldpd *cfg)
{
	/* Setup libevent */
	log_debug("event", "initialize libevent");
	event_set_log_callback(levent_log_cb);
	if (!(cfg->g_base = event_base_new()))
		fatalx("unable to create a new libevent base");
	log_info("event", "libevent %s initialized with %s method",
		  event_get_version(),
		  event_base_get_method(cfg->g_base));

	/* Setup SNMP */
#ifdef USE_SNMP
	if (cfg->g_snmp) {
		agent_init(cfg, cfg->g_snmp_agentx);
		cfg->g_snmp_timeout = evtimer_new(cfg->g_base,
		    levent_snmp_timeout,
		    cfg);
		if (!cfg->g_snmp_timeout)
			fatalx("unable to setup timeout function for SNMP");
		if ((cfg->g_snmp_fds =
			malloc(sizeof(struct ev_l))) == NULL)
			fatalx("unable to allocate memory for SNMP events");
		TAILQ_INIT(levent_snmp_fds(cfg));
	}
#endif

	/* Setup loop that will run every X seconds. */
	log_debug("event", "register loop timer");
	if (!(cfg->g_main_loop = event_new(cfg->g_base, -1, 0,
					   levent_update_and_send,
					   cfg)))
		fatalx("unable to setup main timer");
	event_active(cfg->g_main_loop, EV_TIMEOUT, 1);

	/* Setup unix socket */
	log_debug("event", "register Unix socket");
	TAILQ_INIT(&lldpd_clients);
	evutil_make_socket_nonblocking(cfg->g_ctl);
	if ((cfg->g_ctl_event = event_new(cfg->g_base, cfg->g_ctl,
		    EV_READ|EV_PERSIST, levent_ctl_accept, cfg)) == NULL)
		fatalx("unable to setup control socket event");
	event_add(cfg->g_ctl_event, NULL);

	/* Signals */
	log_debug("event", "register signals");
	signal(SIGHUP, SIG_IGN);
	evsignal_add(evsignal_new(cfg->g_base, SIGUSR1,
		levent_dump, cfg->g_base),
	    NULL);
	evsignal_add(evsignal_new(cfg->g_base, SIGINT,
		levent_stop, cfg->g_base),
	    NULL);
	evsignal_add(evsignal_new(cfg->g_base, SIGTERM,
		levent_stop, cfg->g_base),
	    NULL);
}
Exemplo n.º 4
0
static int
epoll_add(void *arg, struct event *ev)
{
	struct epollop *epollop = arg;
	struct epoll_event epev = {0, {0}};
	struct evepoll *evep;
	int fd, op, events;

    /*
     * x信号的原理
     * 1 设置信号处理函数,保存原来的信号处理函数到event的ev_base->sh_old中去
     * 2 如果是首次添加信号,那么需要为所有信号追加一个信号事件来源自event->ev_base->ev_signal
     *   同时设置event->ev_base->ev_signal->ev_signal_added,表示信号回调事件已经设置了
     * 3 同时把事件追加到event->ev_base->ev_signal->evsigevents[signno]链表中去
     */
	if (ev->ev_events & EV_SIGNAL)  //如果是加入的信号
		return (evsignal_add(ev));

	fd = ev->ev_fd;
	if (fd >= epollop->nfds) {
		/* Extent the file descriptor array as necessary */
        //如果说当前的epoll中已经满足不了新加入的句柄
		if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
			return (-1);
	}

	evep = &epollop->fds[fd];
	op = EPOLL_CTL_ADD;
	events = 0;
    //如果事件之前是可读
	if (evep->evread != NULL) {
		events |= EPOLLIN;
		op = EPOLL_CTL_MOD;
	}
    //如果事件之前是可写
	if (evep->evwrite != NULL) {
		events |= EPOLLOUT;
		op = EPOLL_CTL_MOD;
	}

    //新加入事件设置的是可读事件
	if (ev->ev_events & EV_READ)
		events |= EPOLLIN;
    //新加入事件设置的是可写事件
	if (ev->ev_events & EV_WRITE)
		events |= EPOLLOUT;

	epev.data.ptr = evep;
	epev.events = events;
	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
			return (-1);

	/* Update events responsible */
	if (ev->ev_events & EV_READ)
		evep->evread = ev;
	if (ev->ev_events & EV_WRITE)
		evep->evwrite = ev;

	return (0);
}
Exemplo n.º 5
0
int
main(int argc, char const *argv[])
{
	struct event* sig;
	struct evlearner* lea;
	struct event_base* base;

	if (argc != 2) {
		printf("Usage: %s config\n", argv[0]);
		exit(1);
	}

	base = event_base_new();

	lea = evlearner_init(argv[1], deliver, NULL, base);
	if (lea == NULL) {
		printf("Could not start the learner!\n");
		exit(1);
	}
	
	sig = evsignal_new(base, SIGINT, handle_sigint, base);
	evsignal_add(sig, NULL);
	
	event_base_dispatch(base);

	event_free(sig);
	evlearner_free(lea);
	event_base_free(base);
	
	return 0;
}
Exemplo n.º 6
0
int
main (int argc, char const *argv[])
{
	struct event* sig;
	struct event_base* base;
	struct evproposer* prop;

	if (argc != 3) {
		printf("Usage: %s id config\n", argv[0]);
		exit(1);
	}

	base = event_base_new();
	sig = evsignal_new(base, SIGINT, handle_sigint, base);
	evsignal_add(sig, NULL);
	
	prop = evproposer_init(atoi(argv[1]), argv[2], base);
	if (prop == NULL) {
		printf("Could not start the proposer!\n");
		exit(1);
	}
	
	event_base_dispatch(base);
	
	event_free(sig);
	evproposer_free(prop);
	event_base_free(base);
	
	return 0;
}
Exemplo n.º 7
0
int main(int argc, const char* argv[])
{
	int id;
	struct event* sig;
	struct evacceptor* acc;
	struct event_base* base;

	if(argc != 3){
		printf("Usage %s id config\n", argv[0]);
		return 0;
	}
	/*构建libevent base*/
	base = event_base_new();

	/*读取acceptor id,全局唯一*/
	id = atoi(argv[1]);
	/*创建一个acceptor 的事件响应器*/
	acc = evacceptor_init(id, argv[2], base);
	if(acc == NULL){
		printf("Could not start the acceptor\n");
		return 0;
	}

	sig = evsignal_new(base, SIGINT, handle_sigint, base);
	evsignal_add(sig, NULL);

	event_base_dispatch(base);

	event_free(sig);
	evacceptor_free(acc);
	event_base_free(base);

	return 1;
}
Exemplo n.º 8
0
bool Master::StartMaster(int argc, char *argv[])
{
	if (0 != conf_para.InitPara(argc, argv))
		return false;

	std::cout << "Start Master" << std::endl;

	if (!m_worker.Init(this))
	{
		std::cerr<< "Master: Worker::Init()" << std::endl;
		return false;
	}

	nums_of_child = conf_para.MaxWorker;

	//创建一定数量的worker
	while (nums_of_child > 0)
	{
		switch (fork())
		{
			case -1:
				std::cerr<< "Master: StartMaster(): fork()" << std::endl;
				return false;
			case 0:
				m_worker.Run();
				return true;
			default:
				--nums_of_child;
				break;
		}
	}

	m_base = event_base_new();
	m_exit_event = evsignal_new(m_base, SIGINT, Master::MasterExitSignal, m_base);
	m_chld_event = evsignal_new(m_base, SIGCHLD, Master::MasterChldSignal, this);
	evsignal_add(m_exit_event, NULL);
	evsignal_add(m_chld_event, NULL);
	event_base_dispatch(m_base);

	return true;
}
Exemplo n.º 9
0
int main(int argc, char **argv)
{
  struct event_base *base;
  struct evconnlistener *listener;
  struct sockaddr_in sin;
  struct event *evstop;

  int port = 9876;

  if (argc > 1) {
    port = atoi(argv[1]);
  }
  if (port<=0 || port>65535) {
    puts("Invalid port");
    return 1;
  }

  signal(SIGPIPE, SIG_IGN);

  base = event_base_new();
  if (!base) {
    puts("Couldn't open event base");
    return 1;
  }

  evstop = evsignal_new(base, SIGHUP, signal_cb, base);
  evsignal_add(evstop, NULL);

  /* Clear the sockaddr before using it, in case there are extra
   *          * platform-specific fields that can mess us up. */
  memset(&sin, 0, sizeof(sin));
  /* This is an INET address */
  sin.sin_family = AF_INET;
  /* Listen on 0.0.0.0 */
  sin.sin_addr.s_addr = htonl(0);
  /* Listen on the given port. */
  sin.sin_port = htons(port);

  listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
      LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
      (struct sockaddr*)&sin, sizeof(sin));
  if (!listener) {
    perror("Couldn't create listener");
    return 1;
  }

  event_base_dispatch(base);

  evconnlistener_free(listener);
  event_free(evstop);
  event_base_free(base);
  return 0;
}
Exemplo n.º 10
0
static int
devpoll_add(void *arg, struct event *ev)
{
	struct devpollop *devpollop = arg;
	struct evdevpoll *evdp;
	int fd, events;

	if (ev->ev_events & OPAL_EV_SIGNAL)
		return (evsignal_add(ev));

	fd = ev->ev_fd;
	if (fd >= devpollop->nfds) {
		/* Extend the file descriptor array as necessary */
		if (devpoll_recalc(ev->ev_base, devpollop, fd) == -1)
			return (-1);
	}
	evdp = &devpollop->fds[fd];

	/* 
	 * It's not necessary to OR the existing read/write events that we
	 * are currently interested in with the new event we are adding.
	 * The /dev/poll driver ORs any new events with the existing events
	 * that it has cached for the fd.
	 */

	events = 0;
	if (ev->ev_events & OPAL_EV_READ) {
		if (evdp->evread && evdp->evread != ev) {
		   /* There is already a different read event registered */
		   return(-1);
		}
		events |= POLLIN;
	}

	if (ev->ev_events & OPAL_EV_WRITE) {
		if (evdp->evwrite && evdp->evwrite != ev) {
		   /* There is already a different write event registered */
		   return(-1);
		}
		events |= POLLOUT;
	}

	if (devpoll_queue(devpollop, fd, events) != 0)
		return(-1);

	/* Update events responsible */
	if (ev->ev_events & OPAL_EV_READ)
		evdp->evread = ev;
	if (ev->ev_events & OPAL_EV_WRITE)
		evdp->evwrite = ev;

	return (0);
}
Exemplo n.º 11
0
static int
epoll_add(void *arg, struct event *ev)
{
	struct epollop *epollop = arg;
	struct epoll_event epev = {0, {0}};
	struct evepoll *evep;
	int fd, op, events;
	//signal 的添加部分,直接调用signal添加函数
	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(ev));

	fd = ev->ev_fd;
	//fd总是系统中空闲的最小fd,判断fds是否够,不够扩大
	if (fd >= epollop->nfds) {
		/* Extent the file descriptor array as necessary */
		if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
			return (-1);
	}
	//fds 和 events数组的索引是一致的都是fd
	evep = &epollop->fds[fd];
	op = EPOLL_CTL_ADD;
	events = 0;
	//若相应的fd已经添加了相应的event
	//再次添加回覆盖evepoll中的event指针
	if (evep->evread != NULL) {
		events |= EPOLLIN;
		op = EPOLL_CTL_MOD;
	}
	if (evep->evwrite != NULL) {
		events |= EPOLLOUT;
		op = EPOLL_CTL_MOD;
	}

	if (ev->ev_events & EV_READ)
		events |= EPOLLIN;
	if (ev->ev_events & EV_WRITE)
		events |= EPOLLOUT;

	epev.data.fd = fd;
	epev.events = events;
	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
			return (-1);

	/* Update events responsible */
	if (ev->ev_events & EV_READ)
		evep->evread = ev;
	if (ev->ev_events & EV_WRITE)
		evep->evwrite = ev;

	return (0);
}
Exemplo n.º 12
0
int main()
{
    struct event_base *eb;
    struct event *ev1, *ev2;

    pthread_t pid;

    /*init event_base*/
    eb = event_base_new();
    assert(eb);

    ev1 = evsignal_new(eb, SIGUSR1, signal_handler, (void*)0x1);
    assert(ev1);
    assert(evsignal_add(ev1, NULL) == 0);

    ev2 = evsignal_new(eb, SIGUSR2, signal_handler, (void*)0x2);
    assert(ev2);
    assert(evsignal_add(ev2, NULL) == 0);

    assert(pthread_create(&pid, NULL, emit_signal, NULL) == 0);

    /*start loop*/
    assert(event_base_loop(eb, EVLOOP_ONCE) == 0);

    assert(pthread_join(pid, NULL) == 0);

    assert(evsignal_del(ev1) == 0);
    assert(evsignal_del(ev2) == 0);
    event_free(ev1);
    event_free(ev2);

    /*destroy event_base*/
    event_base_free(eb);

    return 0;
}
Exemplo n.º 13
0
int add_signal(int signum, struct event *event)
{
	if (!event) {
		event = evsignal_new(base, signum, cb_signal, NULL);
		if (!event) {
			log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "%s %d: evsignal_new failed[%d]", __FUNCTION__, __LINE__, errno);					
			return (-1);
		}
		event->ev_arg = event;
	} else {
		evsignal_assign(event, base, signum, event->ev_callback, NULL);
	}

	return evsignal_add(event, NULL);
}
Exemplo n.º 14
0
int main(int argc, char **argv)
{
  struct event_base *base;
  struct evconnlistener *listener;
  struct sockaddr_in sin;
  struct event *evstop;

  int port = 9876;

  if (argc > 1) {
    port = atoi(argv[1]);
  }
  if (port<=0 || port>65535) {
    puts("Invalid port");
    return 1;
  }

  signal(SIGPIPE, SIG_IGN);

  base = event_base_new();
  if (!base) {
    puts("Couldn't open event base");
    return 1;
  }

  evstop = evsignal_new(base, SIGHUP, signal_cb, base);
  evsignal_add(evstop, NULL);

  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(0);
  sin.sin_port = htons(port);

  listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
      LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
      (struct sockaddr*)&sin, sizeof(sin));
  if (!listener) {
    perror("Couldn't create listener");
    return 1;
  }

  event_base_dispatch(base);

  evconnlistener_free(listener);
  event_free(evstop);
  event_base_free(base);
  return 0;
}
Exemplo n.º 15
0
static void logged_in(sp_session *session, sp_error error) {
  if (error != SP_ERROR_OK) {
    fprintf(stderr, "%s\n", sp_error_message(error));
    exit_status = EXIT_FAILURE;
    logged_out(session);
    return;
  }

  struct state *state = sp_session_userdata(session);
  state->session = session;
  evsignal_add(state->sigint, NULL);

  sp_playlistcontainer *pc = sp_session_playlistcontainer(session);
  sp_playlistcontainer_add_callbacks(pc, &playlistcontainer_callbacks,
                                     session);
}
Exemplo n.º 16
0
static int
epoll_add(void *arg, struct event *ev)
{
	struct epollop *epollop = arg;
	struct epoll_event epev = {0, {0}};
	struct evepoll *evep;
	int fd, op, events;

	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(ev));

	fd = ev->ev_fd;
	if (fd >= epollop->nfds) {
		
		if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
			return (-1);
	}
	evep = &epollop->fds[fd];
	op = EPOLL_CTL_ADD;
	events = 0;
	if (evep->evread != NULL) {
		events |= EPOLLIN;
		op = EPOLL_CTL_MOD;
	}
	if (evep->evwrite != NULL) {
		events |= EPOLLOUT;
		op = EPOLL_CTL_MOD;
	}

	if (ev->ev_events & EV_READ)
		events |= EPOLLIN;
	if (ev->ev_events & EV_WRITE)
		events |= EPOLLOUT;

	epev.data.fd = fd;
	epev.events = events;
	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
			return (-1);

	
	if (ev->ev_events & EV_READ)
		evep->evread = ev;
	if (ev->ev_events & EV_WRITE)
		evep->evwrite = ev;

	return (0);
}
Exemplo n.º 17
0
int
epoll_add(void *arg, struct event *ev)
{
	struct epollop *epollop = arg;
	struct epoll_event epev;
	struct evepoll *evep;
	int fd, op, events;

	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(&epollop->evsigmask, ev));

	fd = ev->ev_fd;
	if (fd >= epollop->nfds) {
		/* Extent the file descriptor array as necessary */
		if (epoll_recalc(epollop, fd) == -1)
			return (-1);
	}
	evep = &epollop->fds[fd];  // NOTE: 以fd作为下标 的一个指针,指向数组, 
	op = EPOLL_CTL_ADD;
	events = 0;
	if (evep->evread != NULL) {
		events |= EPOLLIN;
		op = EPOLL_CTL_MOD;
	}
	if (evep->evwrite != NULL) {
		events |= EPOLLOUT;
		op = EPOLL_CTL_MOD;
	}

	if (ev->ev_events & EV_READ)
		events |= EPOLLIN;
	if (ev->ev_events & EV_WRITE)
		events |= EPOLLOUT;

	epev.data.ptr = evep;  // NOTE: 这里作为一个指针
	epev.events = events;  // NOTE 疑问, epev是局部变量,可以直接传指针? 应该是没问题,内核复制一份
	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
			return (-1);

	/* Update events responsible */
	if (ev->ev_events & EV_READ)
		evep->evread = ev;    // 在这里真正复制了 对应的事件  返回的时候就能看到
	if (ev->ev_events & EV_WRITE)
		evep->evwrite = ev;

	return (0);
}
Exemplo n.º 18
0
static int
epoll_add(void *arg, struct event *ev)
{
	struct epollop *epollop = arg;
	struct epoll_event epev = {0, {0}};
	struct evepoll *evep;
	int fd, op, events;

	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(ev));

	fd = ev->ev_fd;
	if (fd >= epollop->nfds) {
		/* Extent the file descriptor array as necessary */
		if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
			return (-1);
	}
	evep = &epollop->fds[fd];
	op = EPOLL_CTL_ADD;
	events = 0;
	if (evep->evread != NULL) {
		events |= EPOLLIN;
		op = EPOLL_CTL_MOD;
	}
	if (evep->evwrite != NULL) {
		events |= EPOLLOUT;
		op = EPOLL_CTL_MOD;
	}

	if (ev->ev_events & EV_READ)
		events |= EPOLLIN;
	if (ev->ev_events & EV_WRITE)
		events |= EPOLLOUT;

	epev.data.ptr = evep;
	epev.events = events;
	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
			return (-1);

	/* Update events responsible */
	if (ev->ev_events & EV_READ)
		evep->evread = ev;
	if (ev->ev_events & EV_WRITE)
		evep->evwrite = ev;

	return (0);
}
Exemplo n.º 19
0
Arquivo: rub.c Projeto: github188/Ptl
static void create_base()
{
	signal(SIGINT,sig_int);
//	strTag->pid = getpid();
	struct event_base *base = event_base_new();
	struct timeval tv = {5,0};
	struct event sig;
	struct event timeout;
	evtimer_assign(&timeout,base,timerout1,&timeout);
	evtimer_add(&timeout,&tv);
	evsignal_assign(&sig,base,SIGUSR2,sig_act1,&sig);
	evsignal_add(&sig,NULL);
	event_base_dispatch(base);
	printf("child break loopbase!!\n");
	event_base_free(base);
	sleep(5);
}
Exemplo n.º 20
0
static int
select_add(void *arg, struct event *ev)
{
	struct selectop *sop = arg;

	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(ev));

	check_selectop(sop);
	/*
	 * Keep track of the highest fd, so that we can calculate the size
	 * of the fd_sets for select(2)
	 */
	if (sop->event_fds < ev->ev_fd) {
		size_t fdsz = sop->event_fdsz;

		if (fdsz < sizeof(fd_mask))
			fdsz = sizeof(fd_mask);

		while (fdsz <
		    (howmany(ev->ev_fd + 1, NFDBITS) * sizeof(fd_mask)))
			fdsz *= 2;

		if (fdsz != sop->event_fdsz) {
			if (select_resize(sop, fdsz)) {
				check_selectop(sop);
				return (-1);
			}
		}

		sop->event_fds = ev->ev_fd;
	}

	if (ev->ev_events & EV_READ) {
		FD_SET(ev->ev_fd, sop->event_readset_in);
		sop->event_r_by_fd[ev->ev_fd] = ev;
	}
	if (ev->ev_events & EV_WRITE) {
		FD_SET(ev->ev_fd, sop->event_writeset_in);
		sop->event_w_by_fd[ev->ev_fd] = ev;
	}
	check_selectop(sop);

	return (0);
}
Exemplo n.º 21
0
static int
evport_add (void *arg, struct event *ev)
{

  struct evport_data *evpd = arg;

  struct fd_info *fdi;
  int factor;

  check_evportop (evpd);

  /*
   * Delegate, if it's not ours to handle.
   */

  if (ev->ev_events & EV_SIGNAL)
    return (evsignal_add (ev) );

  /*
   * If necessary, grow the file descriptor info table
   */

  factor = 1;

  while (ev->ev_fd >= factor * evpd->ed_nevents)
    factor *= 2;

  if (factor > 1)
    {
      if (-1 == grow (evpd, factor) )
        {
          return (-1);
        }
    }

  fdi = &evpd->ed_fds[ev->ev_fd];

  if (ev->ev_events & EV_READ)
    fdi->fdi_revt = ev;

  if (ev->ev_events & EV_WRITE)
    fdi->fdi_wevt = ev;

  return reassociate (evpd, fdi, ev->ev_fd);
}
Exemplo n.º 22
0
void logged_in(sp_session *session, sp_error error) {
  struct state *state = sp_session_userdata(session);

  if (error != SP_ERROR_OK) {
    syslog(LOG_CRIT, "Error logging in to Spotify: %s",
           sp_error_message(error));
    state->exit_status = EXIT_FAILURE;
    logged_out(session);
    return;
  }

  state->session = session;
  evsignal_add(state->sigint, NULL);

  sp_playlistcontainer *pc = sp_session_playlistcontainer(session);
  sp_playlistcontainer_add_callbacks(pc, &playlistcontainer_callbacks,
                                     session);
}
Exemplo n.º 23
0
/* Terminate gracefully on SIGTERM */
void
sigterm_cb(int fd, short event, void * arg) {
    evbase_t     * evbase = (evbase_t *)arg;
    struct timeval tv     = { .tv_usec = 100000, .tv_sec = 0 }; /* 100 ms */

    event_base_loopexit(evbase, &tv);
}

void
init_thread_cb(evhtp_t * htp, evthr_t * thr, void * arg) {
    static int aux = 0;

    printf("Spinning up a thread: %d\n", ++aux);
    evthr_set_aux(thr, &aux);
}

int
main(int argc, char ** argv) {
    struct event *ev_sigterm;
    evbase_t    * evbase  = event_base_new();
    evhtp_t     * evhtp   = evhtp_new(evbase, NULL);

    evhtp_set_gencb(evhtp, frontend_cb, NULL);

#ifndef EVHTP_DISABLE_SSL
    evhtp_ssl_cfg_t scfg1 = { 0 };

    scfg1.pemfile  = "./server.pem";
    scfg1.privfile = "./server.pem";

    evhtp_ssl_init(evhtp, &scfg1);
#endif

    evhtp_use_threads(evhtp, init_thread_cb, 8, NULL);
#ifndef WIN32
    ev_sigterm = evsignal_new(evbase, SIGTERM, sigterm_cb, evbase);
    evsignal_add(ev_sigterm, NULL);
#endif
    evhtp_bind_socket(evhtp, "0.0.0.0", 8081, 1024);
    event_base_loop(evbase, 0);

    printf("Clean exit\n");
    return 0;
}
Exemplo n.º 24
0
LibeventServer::LibeventServer() {
  base_ = event_base_new();

  // Create our event base
  if (!base_) {
    throw ConnectionException("Couldn't open event base");
  }

  // Add hang up signal event
  ev_stop_ =
      evsignal_new(base_, SIGHUP, ControlCallback::Signal_Callback, base_);
  evsignal_add(ev_stop_, NULL);

  // Add timeout event to check server's start/close flag every one second
  struct timeval one_seconds = {1, 0};
  ev_timeout_ = event_new(base_, -1, EV_TIMEOUT | EV_PERSIST,
                          ControlCallback::ServerControl_Callback, this);
  event_add(ev_timeout_, &one_seconds);

  // a master thread is responsible for coordinating worker threads.
  master_thread_ =
      std::make_shared<LibeventMasterThread>(CONNECTION_THREAD_COUNT, base_);

  port_ = FLAGS_port;
  max_connections_ = FLAGS_max_connections;
  private_key_file_ = FLAGS_private_key_file;
  certificate_file_ = FLAGS_certificate_file;

  // For logging purposes
  //  event_enable_debug_mode();
  //  event_set_log_callback(LogCallback);

  // Commented because it's not in the libevent version we're using
  // When we upgrade this should be uncommented
  //  event_enable_debug_logging(EVENT_DBG_ALL);

  // Ignore the broken pipe signal
  // We don't want to exit on write when the client disconnects
  signal(SIGPIPE, SIG_IGN);
}
Exemplo n.º 25
0
static void
lgtd_setup_signal_handling(void)
{
    for (int i = 0; i != LGTD_ARRAY_SIZE(lgtd_signals); i++) {
        lgtd_signal_evs[i] = evsignal_new(
            lgtd_ev_base,
            lgtd_signals[i],
            lgtd_signal_event_callback,
            // event_self_cbarg() would make things cleaner, but this was
            // unfortunately added in libevent 2.1 which hasn't been released
            // as of 2016:
            (void *)(intptr_t)i // cast twice for -Wint-to-void-pointer-cast
        );
        if (!lgtd_signal_evs[i] || evsignal_add(lgtd_signal_evs[i], NULL)) {
            lgtd_err(1, "can't configure signal handling");
        }
    }

    struct sigaction act = { .sa_handler = SIG_IGN };
    if (sigaction(SIGPIPE, &act, NULL)) {
        lgtd_err(1, "can't configure signal handling");
    }
}
Exemplo n.º 26
0
int main(int argc, char **argv)
{
    struct context ctx = {0};
    struct event *signal_int;
    struct evhttp_bound_socket *handle;
    char listen_addr[256];

    if (argc != 2)
    {
        printf("usage: statsrv STATS\n");
        return -1;
    }

    if (stats_cl_create(&ctx.cl) != S_OK)
    {
        printf("Failed to allocate stats counter list\n");
        return ERROR_FAIL;
    }

    if (stats_sample_create(&ctx.sample) != S_OK)
    {
        printf("Failed to allocate stats sample\n");
        return ERROR_FAIL;
    }

    if (stats_sample_create(&ctx.prev_sample) != S_OK)
    {
        printf("Failed to allocate stats sample\n");
        return ERROR_FAIL;
    }

    ctx.stats = open_stats(argv[1]);
    if (!ctx.stats)
    {
        printf("Failed to open stats %s\n", argv[1]);
        return ERROR_FAIL;
    }

    ctx.base = event_base_new();
    if (!ctx.base)
    {
        printf("Could not allocate event base\n");
        return 1;
    }

    /* add a handler for SIGINT */
    signal_int = evsignal_new(ctx.base, SIGINT, sigint_cb, event_self_cbarg());
    evsignal_add(signal_int,0);

    /* Create a new evhttp object to handle requests. */
    ctx.http = evhttp_new(ctx.base);
    if (!ctx.http)
    {
        printf("could not create evhttp.\n");
        return ERROR_FAIL;
    }

    evhttp_set_gencb(ctx.http, http_request_cb, &ctx);

    /* Now we tell the evhttp what port to listen on */
    handle = evhttp_bind_socket_with_handle(ctx.http, "0.0.0.0", 8080);
    if (!handle)
    {
        printf("couldn't bind to http port %d.\n", (int)8080);
        return ERROR_FAIL;
    }

    if (http_get_address(handle, listen_addr, sizeof(listen_addr)) == S_OK)
        printf("http: listening at %s\n", listen_addr);

    event_base_dispatch(ctx.base);

    event_free(signal_int);

#if 0
    start_time = current_time();

    while (!signal_received)
    {
        err = stats_get_sample(stats,cl,sample);
        if (err != S_OK)
        {
            printf("Error %08x (%s) getting sample\n",err,error_message(err));
        }

        clear();

        sample_time = TIME_DELTA_TO_NANOS(start_time, sample->sample_time);

        mvprintw(0,0,"SAMPLE @ %6lld.%03llds  SEQ:%d\n", sample_time / 1000000000ll, (sample->sample_time % 1000000000ll) / 1000000ll, sample->sample_seq_no);

        n = 1;
        maxy = getmaxy(stdscr);
        col = 0;
        for (j = 0; j < cl->cl_count; j++)
        {
            counter_get_key(cl->cl_ctr[j],counter_name,MAX_COUNTER_KEY_LENGTH+1);
            mvprintw(n,col+0,"%s", counter_name);
            mvprintw(n,col+29,"%15lld", stats_sample_get_value(sample,j));
            mvprintw(n,col+46,"%15lld", stats_sample_get_delta(sample,prev_sample,j));
            if (++n == maxy)
            {
                col += 66;
                n = 1;
            }
        }
        refresh();

        tmp = prev_sample;
        prev_sample = sample;
        sample = tmp;

        FD_ZERO(&fds);
        FD_SET(0,&fds);

        now = current_time();

        tv.tv_sec = 0;
        tv.tv_usec = 1000000 - (now % 1000000000) / 1000;

        ret = select(1, &fds, NULL, NULL, &tv);
        if (ret == 1)
        {
            ch = getch();
            if (ch == 'c' || ch == 'C')
            {
                stats_reset_counters(stats);
            }
        }
    }

    close_screen();
#endif

    if (ctx.base)
        event_base_free(ctx.base);

    if (ctx.http)
        evhttp_free(ctx.http);

    if (ctx.stats)
    {
        stats_close(ctx.stats);
        stats_free(ctx.stats);
    }

    if (ctx.cl)
        stats_cl_free(ctx.cl);

    if (ctx.sample)
        stats_sample_free(ctx.sample);

    if (ctx.prev_sample)
        stats_sample_free(ctx.prev_sample);

    return 0;
}
Exemplo n.º 27
0
static int
poll_add(void *arg, struct event *ev)
{
	struct pollop *pop = arg;
	struct pollfd *pfd = NULL;
	int i;

	if (ev->ev_events & EV_SIGNAL)
		return (evsignal_add(ev));
	if (!(ev->ev_events & (EV_READ|EV_WRITE)))
		return (0);

	poll_check_ok(pop);
	if (pop->nfds + 1 >= pop->event_count) {
		struct pollfd *tmp_event_set;
		struct event **tmp_event_r_back;
		struct event **tmp_event_w_back;
		int tmp_event_count;

		if (pop->event_count < 32)
			tmp_event_count = 32;
		else
			tmp_event_count = pop->event_count * 2;

		/* We need more file descriptors */
		tmp_event_set = realloc(pop->event_set,
				 tmp_event_count * sizeof(struct pollfd));
		if (tmp_event_set == NULL) {
			event_warn("realloc");
			return (-1);
		}
		pop->event_set = tmp_event_set;

		tmp_event_r_back = realloc(pop->event_r_back,
			    tmp_event_count * sizeof(struct event *));
		if (tmp_event_r_back == NULL) {
			/* event_set overallocated; that's okay. */
			event_warn("realloc");
			return (-1);
		}
		pop->event_r_back = tmp_event_r_back;

		tmp_event_w_back = realloc(pop->event_w_back,
			    tmp_event_count * sizeof(struct event *));
		if (tmp_event_w_back == NULL) {
			/* event_set and event_r_back overallocated; that's
			 * okay. */
			event_warn("realloc");
			return (-1);
		}
		pop->event_w_back = tmp_event_w_back;

		pop->event_count = tmp_event_count;
	}
	if (ev->ev_fd >= pop->fd_count) {
		int *tmp_idxplus1_by_fd;
		int new_count;
		if (pop->fd_count < 32)
			new_count = 32;
		else
			new_count = pop->fd_count * 2;
		while (new_count <= ev->ev_fd)
			new_count *= 2;
		tmp_idxplus1_by_fd =
			realloc(pop->idxplus1_by_fd, new_count * sizeof(int));
		if (tmp_idxplus1_by_fd == NULL) {
			event_warn("realloc");
			return (-1);
		}
		pop->idxplus1_by_fd = tmp_idxplus1_by_fd;
		memset(pop->idxplus1_by_fd + pop->fd_count,
		       0, sizeof(int)*(new_count - pop->fd_count));
		pop->fd_count = new_count;
	}

	i = pop->idxplus1_by_fd[ev->ev_fd] - 1;
	if (i >= 0) {
		pfd = &pop->event_set[i];
	} else {
		i = pop->nfds++;
		pfd = &pop->event_set[i];
		pfd->events = 0;
		pfd->fd = ev->ev_fd;
		pop->event_w_back[i] = pop->event_r_back[i] = NULL;
		pop->idxplus1_by_fd[ev->ev_fd] = i + 1;
	}

	pfd->revents = 0;
	if (ev->ev_events & EV_WRITE) {
		pfd->events |= POLLOUT;
		pop->event_w_back[i] = ev;
	}
	if (ev->ev_events & EV_READ) {
		pfd->events |= POLLIN;
		pop->event_r_back[i] = ev;
	}
	poll_check_ok(pop);

	return (0);
}
Exemplo n.º 28
0
int main(int argc, char** argv)
{
	/* Set the CWD */
	char *home = getenv("HOME");
	if (!home) {
		printf("Failed to load data directory\n");
		return EXIT_FAILURE;
	}
	
	char *datadir = malloc(strlen(home) + 10);
	snprintf(datadir, strlen(home) + 10, "%s/.bitpeer", home);
	
	if (chdir(datadir) < 0) {
		if (mkdir(datadir, 0777) < 0) {
			printf("Failed to create data directory.\n");
			return EXIT_FAILURE;
		}
		
		if (chdir(datadir) < 0) {
			printf("Failed to chdir\n");
			return EXIT_FAILURE;
		}
	}
	
	free(datadir);
	
	/* For safety we do these protocol struct assertions */
	assert(sizeof(bp_proto_message_s) == 24);
	assert(sizeof(bp_proto_net_addr_s) == 26);
	assert(sizeof(bp_proto_net_addr_full_s) == 30);
	assert(sizeof(bp_proto_version_s) == 80);
	assert(sizeof(bp_proto_inv_s) == 36);
	assert(sizeof(bp_btcblock_header_s) == 80);
	
	/* Set the settings */
	bp_program_s program;
	memset(&program, 0, sizeof(program));
	program.addrpool_size = 20480;
	program.min_connections = 8;
	program.max_connections = 4096;
	program.reindex_blocks = 0;
	program.relay_transactions = 1;
	program.relay_blocks = 1;
	program.txpool_size = 1024;
	program.blocks_per_getblocks = 500;
	
	/* Interpret the command line */
	if (argc < 2) {
		printf("Invalid command line arguments.\n");
		printf("Usage:  bitpeer [listen_port] [public_ip] -n [seed_node]\n");
		printf("public_ip and seed_node may optionally contain a port number.\n");
		return EXIT_FAILURE;
	}
	
	unsigned short listen_port = atoi(argv[1]);
	if (listen_port == 0) {
		printf("Invalid port number specified. Valid ports go from 1 to 65535.\n");
		return EXIT_FAILURE;
	}
	
	struct sockaddr_in6 sockaddr;
	int sockaddr_len = sizeof(struct sockaddr_in6);
	if (evutil_parse_sockaddr_port(argv[2], (struct sockaddr*)&sockaddr, &sockaddr_len) < 0) {
		printf("Invalid public_ip specified\n");
		return EXIT_FAILURE;
	}
	if (sockaddr.sin6_family == AF_INET) {
		sockaddr = bp_in4to6((struct sockaddr_in*)&sockaddr);
		sockaddr_len = sizeof(struct sockaddr_in6);
	}
	if (sockaddr.sin6_port == 0) {
		sockaddr.sin6_port = ntohs(listen_port);
	}
	
	int nodecount = 0;
	struct sockaddr_in6 *nodeaddrs = NULL;
	int *nodelens = NULL;
	int *nodeperm = NULL;
	
	/* Now interpret the optional arguments */
	// Quick preprocessor macro to go to the next argv
	
#define NEXT_I() {i++; if (i >= argc) { printf("Argument for %s missing\n", argv[i-1]); return EXIT_FAILURE; }}
	for (int i = 3; i < argc; i++) {
		if (strcmp(argv[i], "--reindex") == 0) {
			program.reindex_blocks = 1;
		}
		else if (strcmp(argv[i], "--addnode") == 0  || strcmp(argv[i], "-n") == 0 ||
				 strcmp(argv[i], "--addpnode") == 0 || strcmp(argv[i], "-p") == 0) {
			NEXT_I();
			nodeaddrs = realloc(nodeaddrs, (nodecount+1) * sizeof(struct sockaddr_in6));
			nodelens = realloc(nodelens, (nodecount+1) * sizeof(int));
			nodeperm = realloc(nodeperm, (nodecount+1) * sizeof(int));
			nodelens[nodecount] = sizeof(struct sockaddr_in6);
			nodeperm[nodecount] = 0;
			
			if (strcmp(argv[i-1], "--addpnode") == 0 || strcmp(argv[i-1], "-p") == 0) {
				printf("Adding a permanent node\n");
				nodeperm[nodecount] = 1;
			}
			
			struct sockaddr_in6 *addr = &nodeaddrs[nodecount];
			memset(addr, 0, sizeof(struct sockaddr_in6));
			
			if (evutil_parse_sockaddr_port(argv[i], (struct sockaddr*)addr, nodelens+nodecount) < 0) {
				printf("Invalid node address specified: %s %d\n", argv[i], nodelens[nodecount]);
				return EXIT_FAILURE;
			}
			if (addr->sin6_family == AF_INET) {
				*addr = bp_in4to6((struct sockaddr_in*)addr);
				nodelens[nodecount] = sizeof(struct sockaddr_in6);
			}
			assert(addr->sin6_family == AF_INET6);
			
			if (addr->sin6_port == 0) addr->sin6_port = ntohs(8333);
			
			nodecount += 1;
		}
		else if (strcmp(argv[i], "--txpool") == 0) {
			NEXT_I();
			program.txpool_size = atoi(argv[i]);
			if (program.txpool_size <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--addrpool") == 0) {
			NEXT_I();
			program.addrpool_size = atoi(argv[i]);
			if (program.addrpool_size <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--getblocks-limit") == 0) {
			NEXT_I();
			program.blocks_per_getblocks = atoi(argv[i]);
			if (program.blocks_per_getblocks == 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--no-tx") == 0) {
			program.relay_transactions = 0;
		}
		else if (strcmp(argv[i], "--no-blocks") == 0) {
			program.relay_blocks = 0;
		}
		else if (strcmp(argv[i], "--minconn") == 0) {
			NEXT_I();
			program.min_connections = atoi(argv[i]);
		}
		else if (strcmp(argv[i], "--maxconn") == 0) {
			NEXT_I();
			program.max_connections = atoi(argv[i]);
			if (program.max_connections <= 0) {
				printf("Invalid argument for %s\n", argv[i-1]);
				return EXIT_FAILURE;
			}
		}
		else if (strcmp(argv[i], "--evdebug") == 0) {
#ifdef EVENT_DBG_ALL
			event_enable_debug_logging(EVENT_DBG_ALL);
#endif
			event_set_log_callback(log_cb);
			event_enable_debug_mode();
		}
		else {
			printf("Unknown argument '%s'\n", argv[i]);
			return EXIT_FAILURE;
		}
	}
	
	/* Ignore SIGPIPE */
	struct sigaction act;
	act.sa_handler = SIG_IGN;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGPIPE, &act, NULL);
	
	/* Create the main loop */
	bp_program_init(&program);
	
	program.eventbase = event_base_new();

	/* Set up the signal handler */
	struct event *signal_event = evsignal_new(program.eventbase, SIGINT, signal_cb, &program);
	evsignal_add(signal_event, NULL);
	
	/* Create a server */
	bp_server_s server;
	program.server = &server;
	bp_server_init(&server, &program, (char*)&sockaddr.sin6_addr, ntohs(sockaddr.sin6_port));
	if (bp_server_listen(&server, listen_port) < 0) {
		return EXIT_FAILURE;
	}
	
	/* We need to connect to one initial node in order to seed everything.
	   We will not do this initial discovery ourselves. */
	for (int i = 0; i < nodecount; i++) {
		bp_connection_s *seed_connection = malloc(sizeof(bp_connection_s));
		int status = bp_connection_connect(seed_connection, &server, &nodeaddrs[i], nodelens[i]);
		if (status < 0) {
			printf("Connecting failed\n");
		}
		seed_connection->is_seed = 1;
		seed_connection->is_permanent = nodeperm[i];
	}
	
	free(nodeaddrs);
	free(nodelens);
	free(nodeperm);
	
	/* Run the loop */
	event_base_loop(program.eventbase, 0);
	printf("Entering clean shutdown state\n");

	/* It would appear that our loop ended, so clean up */
	event_free(signal_event);
	bp_server_deinit(&server);
	
	bp_program_deinit(&program);
	event_base_free(program.eventbase);
	
	return EXIT_SUCCESS;
}
Exemplo n.º 29
0
int add_signal(lz_event_base_t base, int signal, signal_fn callb, void *arg){
    event *ev = evsignal_new((struct event_base *)base, signal, callb, arg);
    signals.push_back(ev);
    return evsignal_add(ev, NULL);
}
Exemplo n.º 30
0
int main(int argc, char **argv)
{
	int error;
	app_subsys **ss;
	int exit_signals[2] = {SIGTERM, SIGINT};
	struct event terminators[2];
    struct event dumper;
	bool conftest = false;
	int opt;
	int i;

	red_srand();
	while ((opt = getopt(argc, argv, "h?vtc:p:")) != -1) {
		switch (opt) {
		case 't':
			conftest = true;
			break;
		case 'c':
			confname = optarg;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'v':
			puts(redsocks_version);
			return EXIT_SUCCESS;
		default:
			printf(
				"Usage: %s [-?hvt] [-c config] [-p pidfile]\n"
				"  -h, -?       this message\n"
				"  -v           print version\n"
				"  -t           test config syntax\n"
				"  -p           write pid to pidfile\n",
				argv[0]);
			return (opt == '?' || opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE;
		}
	}


	FILE *f = fopen(confname, "r");
	if (!f) {
		perror("Unable to open config file");
		return EXIT_FAILURE;
	}

	parser_context* parser = parser_start(f, NULL);
	if (!parser) {
		perror("Not enough memory for parser");
		return EXIT_FAILURE;
	}

	FOREACH(ss, subsystems)
		if ((*ss)->conf_section)
			parser_add_section(parser, (*ss)->conf_section);
	error = parser_run(parser);
	parser_stop(parser);
	fclose(f);

	if (error)
		return EXIT_FAILURE;

	if (conftest)
		return EXIT_SUCCESS;

	// Initialize global event base
	g_event_base = event_base_new();
	if (!g_event_base)
		return EXIT_FAILURE;
		
	memset(&dumper, 0, sizeof(dumper));
	memset(terminators, 0, sizeof(terminators));

	FOREACH(ss, subsystems) {
		if ((*ss)->init) {
			error = (*ss)->init();
			if (error)
				goto shutdown;
		}
	}

	if (pidfile) {
		f = fopen(pidfile, "w");
		if (!f) {
			perror("Unable to open pidfile for write");
			return EXIT_FAILURE;
		}
		fprintf(f, "%d\n", getpid());
		fclose(f);
	}

	assert(SIZEOF_ARRAY(exit_signals) == SIZEOF_ARRAY(terminators));
	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		evsignal_assign(&terminators[i], get_event_base(), exit_signals[i], terminate, NULL);
		if (evsignal_add(&terminators[i], NULL) != 0) {
			log_errno(LOG_ERR, "signal_add");
			goto shutdown;
		}
	}

    evsignal_assign(&dumper, get_event_base(), SIGUSR1, dump_handler, NULL);
    if (evsignal_add(&dumper, NULL) != 0) {
        log_errno(LOG_ERR, "evsignal_add");
        goto shutdown;
    }

	log_error(LOG_NOTICE, "redsocks started");

	event_base_dispatch(g_event_base);

	log_error(LOG_NOTICE, "redsocks goes down");

shutdown:
    if (evsignal_initialized(&dumper)) {
        if (evsignal_del(&dumper) != 0)
		    log_errno(LOG_WARNING, "signal_del");
        memset(&dumper, 0, sizeof(dumper));
    }

	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		if (evsignal_initialized(&terminators[i])) {
			if (evsignal_del(&terminators[i]) != 0)
				log_errno(LOG_WARNING, "signal_del");
			memset(&terminators[i], 0, sizeof(terminators[i]));
		}
	}

	for (--ss; ss >= subsystems; ss--)
		if ((*ss)->fini)
			(*ss)->fini();

	if (g_event_base)
		event_base_free(g_event_base);
	
	return !error ? EXIT_SUCCESS : EXIT_FAILURE;
}