int emc_init_server(struct emc_server_context *ctx) { int result; int max_workers; char *emc_data_file; g_thread_init(NULL); max_workers = emc_config_table_get_or_default_int("emc_max_workers", EMC_DEFAULT_MAX_WORKERS); emc_data_file = emc_config_table_get("emc_data_file"); ctx->nuauth_directory = g_tree_new( emc_netmask_order_func ); result = emc_parse_datafile(ctx, emc_data_file); if (result < 0) { return -1; } loop = ev_default_loop(0); result = emc_setup_servers(loop, ctx); if (result < 0) { return -1; } ev_signal_init(&sigint_watcher, sigint_cb, SIGINT); ev_signal_start(loop, &sigint_watcher); ev_signal_init(&sigterm_watcher, sigint_cb, SIGTERM); ev_signal_start(loop, &sigterm_watcher); ev_signal_init(&sigusr1_watcher, sigusr1_cb, SIGUSR1); ev_signal_start(loop, &sigusr1_watcher); ev_async_init(&client_ready_signal, emc_client_ready_cb); ev_async_start(loop, &client_ready_signal); ctx->continue_processing = 1; sigint_watcher.data = ctx; sigterm_watcher.data = ctx; sigusr1_watcher.data = ctx; client_ready_signal.data = ctx; g_thread_pool_set_max_unused_threads( (int)(max_workers/2) ); ctx->pool_tls_handshake = g_thread_pool_new((GFunc)emc_worker_tls_handshake, NULL, max_workers, FALSE, NULL); ctx->pool_reader = g_thread_pool_new((GFunc)emc_worker_reader, NULL, max_workers, FALSE, NULL); ctx->work_queue = g_async_queue_new(); ctx->tls_client_list_mutex = g_mutex_new(); log_printf(DEBUG_LEVEL_DEBUG, "Max: %d", g_thread_pool_get_max_unused_threads()); return 0; }
void supervisor_thread_run(supervisor_thread_t *thiz) { LOG_LOC; LOG_DEBUG("[TID] 0x%zx %s\n", (size_t)pthread_self(), __FUNCTION__); ev_io_start(thiz->event_loop, &thiz->udp_read_watcher); ev_io_start(thiz->event_loop, &thiz->inbox_watcher); ev_signal_start(thiz->event_loop, &thiz->sigint_watcher); ev_signal_start(thiz->event_loop, &thiz->sigchld_watcher); // now wait for events to arrive ev_loop(thiz->event_loop, 0); return; }
int initialize_connections(EV_P) { ev_signal *sigpipe_watcher = malloc(sizeof(ev_signal)); ev_signal_init(sigpipe_watcher, sigpipe_cb, SIGPIPE); ev_signal_start(EV_A_ sigpipe_watcher); ev_signal *sigint_watcher = malloc(sizeof(ev_signal)); ev_signal_init(sigint_watcher, shutdown_server, SIGINT); ev_signal_start(EV_A_ sigint_watcher); active_connections = dictCreate(&connectionDict, NULL); return 0; }
/** * Setups and starts main event loop. */ void event_loop_init(EV_P) { LOGGER_info("call"); /*=== Setting up event loop ==*/ /* signals */ ev_signal_init(&sigint_watcher, sigint_cb, SIGINT); ev_signal_start(EV_A_ & sigint_watcher); ev_signal_init(&sigalrm_watcher, sigalrm_cb, SIGALRM); ev_signal_start(EV_A_ & sigalrm_watcher); ev_signal_init(&sigpipe_watcher, sigpipe_cb, SIGPIPE); ev_signal_start(EV_A_ & sigpipe_watcher); return; }
static void feng_handle_signals() { sigset_t block_set; ev_signal *sig = &signal_watcher_int; ev_signal_init (sig, sigint_cb, SIGINT); ev_signal_start (feng_loop, sig); sig = &signal_watcher_term; ev_signal_init (sig, sigint_cb, SIGTERM); ev_signal_start (feng_loop, sig); /* block PIPE signal */ sigemptyset(&block_set); sigaddset(&block_set, SIGPIPE); sigprocmask(SIG_BLOCK, &block_set, NULL); }
shared_ptr<event_signal_watcher> events::onSignal(int signal, function<void(event_signal_watcher*)> callback) { auto e_spec = new_watcher<event_signal_watcher>(callback); ev_signal_init(&e_spec->watcher, events::signal_callback, signal); ev_signal_start(this->loop, &e_spec->watcher); signal_watchers.push_back(e_spec); return e_spec; }
int main(int argc, char *argv[]) { struct ev_loop *loop = EV_DEFAULT; ev_signal sig_watcher; struct mg_mgr mgr; ev_signal_init(&sig_watcher, signal_cb, SIGINT); ev_signal_start(loop, &sig_watcher); mg_mgr_init(&mgr, NULL, loop); /* Process command line arguments */ if (argc != 2) { fprintf(stderr, "Usage: %s <domain>\n", argv[0]); exit(0); } mg_resolve_async(&mgr, argv[1], MG_DNS_A_RECORD, dns_resolve_cb, argv[1]); ev_run(loop, 0); printf("exit...\n"); mg_mgr_free(&mgr); return 0; }
LWS_VISIBLE int lws_initloop( struct lws_context *context, struct ev_loop *loop) { int status = 0; int backend; const char * backend_name; struct ev_io *w_accept = &context->w_accept.watcher; struct ev_signal *w_sigint = &context->w_sigint.watcher; if (!loop) loop = ev_default_loop(0); context->io_loop = loop; /* * Initialize the accept w_accept with the listening socket * and register a callback for read operations: */ ev_io_init(w_accept, lws_accept_cb, context->lserv_fd, EV_READ); ev_io_start(context->io_loop,w_accept); /* Register the signal watcher unless the user has indicated otherwise: */ if( context->use_ev_sigint ) { ev_signal_init(w_sigint, context->lws_ev_sigint_cb, SIGINT); ev_signal_start(context->io_loop,w_sigint); }; backend = ev_backend(loop); switch (backend) { case EVBACKEND_SELECT: backend_name = "select"; break; case EVBACKEND_POLL: backend_name = "poll"; break; case EVBACKEND_EPOLL: backend_name = "epoll"; break; case EVBACKEND_KQUEUE: backend_name = "kqueue"; break; case EVBACKEND_DEVPOLL: backend_name = "/dev/poll"; break; case EVBACKEND_PORT: backend_name = "Solaris 10 \"port\""; break; default: backend_name = "Unknown libev backend"; break; }; lwsl_notice(" libev backend: %s\n", backend_name); return status; }
/***************************************************************************** * Signal Handler *****************************************************************************/ static void signal_watcher_init(struct ev_signal *w, struct ev_loop *loop, void (*cb)(struct ev_loop*, struct ev_signal*, int), int signum) { ev_signal_init(w, cb, signum); ev_signal_start(loop, w); ev_unref(loop); }
/* Procedure exposed in Python will generate and start the event loop */ static PyObject *py_run_loop(PyObject *self, PyObject *args) { char *backend=""; int i; ev_io accept_watcher; ev_signal signal_watcher, signal_watcher2, signal_watcher3; struct TimerObj *timer; loop = ev_default_loop (0); switch (ev_backend(loop)) { case 1: backend="select"; break; case 2: backend="poll"; break; case 4: backend="epoll"; break; case 8: backend="kqueue"; break; } printf("Using %s as event backend\n", backend); ev_io_init(&accept_watcher,accept_cb,sockfd,EV_READ); ev_io_start(loop,&accept_watcher); ev_signal_init(&signal_watcher, sigint_cb, SIGINT); ev_signal_start(loop, &signal_watcher); ev_signal_init(&signal_watcher2, sigpipe_cb, SIGPIPE); ev_signal_start(loop, &signal_watcher2); ev_signal_init(&signal_watcher3, sigterm_cb, SIGTERM); ev_signal_start(loop, &signal_watcher3); idle_watcher = malloc(sizeof(ev_idle)); ev_idle_init(idle_watcher, idle_cb); if (list_timers_i>=0) { for (i=0; i<list_timers_i; i++) { timer=list_timers[i]; ev_timer_init(&timer->timerwatcher, timer_cb, timer->delay, timer->delay); ev_timer_start(loop, &timer->timerwatcher); } } ev_loop (loop, 0); return Py_None; }
int luv_activate_signal_handler(lua_State* L) { int signal = luaL_checkint(L, 1); struct ev_signal* signal_watcher = (struct ev_signal*)malloc(sizeof(struct ev_signal)); signal_watcher->data = L; ev_signal_init (signal_watcher, luv_on_signal, signal); struct ev_loop* loop = uv_default_loop()->ev; ev_signal_start (loop, signal_watcher); return 0; }
const char* slave_run_cb(void) { struct ev_loop *loop; ev_io io_listen; ev_signal sigint_listen; ev_signal sigterm_listen; pthread_mutex_init(&srv.pending_lk, 0); pthread_mutex_init(&srv.clients_lk, 0); if (!(loop = ev_default_loop(EVFLAG_AUTO))) return 1; syslog(LOG_INFO, "listening on %s:%hd", inet_ntoa(srv.addr.sin_addr), ntohs(srv.addr.sin_port)); ev_signal_init(&sigint_listen, &nol_s_ev_sigint, SIGINT); ev_signal_init(&sigterm_listen, &nol_s_ev_sigint, SIGTERM); ev_io_init(&io_listen, &nol_s_ev_conn_accept, srv.listen_sock, EV_READ); ev_io_init(&srv.master_io, &nol_s_ev_master, srv.master_sock, EV_READ); ev_async_init(&srv.client_status, &nol_s_ev_client_status); /* catch SIGINT so we can close connections and clean up properly */ ev_signal_start(loop, &sigint_listen); ev_signal_start(loop, &sigterm_listen); ev_io_start(loop, &io_listen); ev_io_start(loop, &srv.master_io); ev_async_start(loop, &srv.client_status); /** * This loop will listen for new connections and data from * the master. **/ ev_loop(loop, 0); close(srv.listen_sock); ev_default_destroy(); closelog(); pthread_mutex_destroy(&srv.pending_lk); pthread_mutex_destroy(&srv.clients_lk); nol_s_hook_invoke(HOOK_CLEANUP); return 0; }
void start_watchers(struct ev_loop *loop) { ev_io_start(loop, &bspwm_watcher); ev_timer_again(loop, &wifi_timer); ev_timer_again(loop, &battery_watcher); ev_timer_again(loop, &sound_watcher); ev_io_start(loop, &packages_io_watcher); ev_periodic_start(loop, &clock_watcher); ev_signal_start(loop, &signal_watcher); ev_prepare_start(loop, &prepare_display); }
int main(int argc, char argv[]) { EV_P = ev_default_loop(0); ev_init(&async_watcher, async_callback); ev_async_start(EV_A, &async_watcher); ev_signal sigint_watcher; ev_init(&sigint_watcher, sigint_callback); ev_signal_set(&sigint_watcher, SIGINT); ev_signal_start(EV_A, &sigint_watcher); ev_signal sigquit_watcher; ev_init(&sigquit_watcher, sigquit_callback); ev_signal_set(&sigquit_watcher, SIGQUIT); ev_signal_start(EV_A, &sigquit_watcher); ev_run(EV_A, 0); return 0; }
void *MainService(void * arg) { status=INITIALIZE; if(init("config","orderid")){ puts("Initialization error."); exit(1); } else status=READY; update_display("default.png",0); libusb_init(NULL); handle=libusb_open_device_with_vid_pid(NULL,USB_VENDORID,USB_PRODUCTID); if(!handle) { printf("OPEN DEVICE ERROR.\n"); getchar(); exit(1); } libusb_claim_interface(handle,0); pthread_t readusb_thread; main_thread=pthread_self(); struct ev_loop *loop = EV_DEFAULT; ev_init (&net_watcher, net_cb); ev_signal_init(&usb_watcher,usb_cb,SIGUSR1); ev_signal_start(loop,&usb_watcher); if(pthread_create(&readusb_thread,NULL,read_from_usb,NULL)) { printf("CREATE THREAD ERROR.\n"); getchar(); exit(1); } while(1) { if(!ev_is_active(EV_A_ &net_watcher)) { ev_io_set (&net_watcher, fd_net, EV_READ); ev_io_start(loop,&net_watcher); } ev_run (loop, 0); if(net_io) ev_io_stop (EV_A_ &net_watcher); } munmap((void *)p_order_id,sizeof(unsigned int)); ghttp_close(request); ghttp_request_destroy(request); return 0; }
// ///////////////////////////////////////////////////////////////////////////// // main loop SCM joystick_loop(SCM jsdevice) { /* open the joystick device */ /* we're only waiting on one joystick at a time for now, so we're going to use a single * variable. TODO: handle multiple joysticks. */ char* jsdevice_c = scm_to_locale_string(jsdevice); jsfd = open(jsdevice_c, O_RDONLY); // check to make sure our joystick is real if (jsfd < 0) { printf("Could not open device %s: %s\n", jsdevice_c, strerror(errno)); return SCM_BOOL_F; } // clean up the filename string. free(jsdevice_c); // set up event loop struct ev_loop* loop = ev_default_loop(0); // set up and run watchers // file watcher waiting for new events from the joystick. this is where joystick data gets into // xbindjoy and where procedures bound to buttons are called from. ev_io js_watcher; ev_init(&js_watcher, js_callback); ev_io_set(&js_watcher, jsfd, EV_READ); ev_io_start(loop, &js_watcher); // timer watcher that pings at a regular (30hz-ish) rate. this is where procedures bound to // axes are called from. ev_timer timer_watcher; ev_init(&timer_watcher, timer_callback); ev_timer_set(&timer_watcher, 0.0, target_timing); ev_timer_start(loop, &timer_watcher); clock_gettime(CLOCK_MONOTONIC, &last_time); // signal watcher. safely clean up and exit on SIGINT. ev_signal sigint_watcher; ev_signal_init(&sigint_watcher, sigint_callback, SIGINT); ev_signal_start(loop, &sigint_watcher); // run the event loop and wait for events to start coming in ev_run(loop, 0); // close file descriptors. close(jsfd); // return success return SCM_BOOL_T; }
static void foreign_event_loop_init_and_run_libev(void) { /* we create and start our "foreign loop" */ loop_ev = ev_loop_new(0); ev_signal_init(&sighandler_ev, signal_cb_ev, SIGINT); ev_signal_start(loop_ev, &sighandler_ev); ev_timer_init(&timer_outer_ev, timer_cb_ev, 0, 1); ev_timer_start(loop_ev, &timer_outer_ev); ev_run(loop_ev, 0); }
static void ircd () { struct ev_loop *loop; /* reopn stderr to log to ircd.err */ logfile = freopen("ircd.err", "w", stderr); if (logfile == NULL) { fprintf(stderr, "freopen: ircd.err: %s\n", strerror(errno)); fprintf(stderr, "logging to stderr instead\n"); } /* bind/listen server socket */ server_fd = unix_listen(IRCD_HOST, IRCD_PORT); if (server_fd == -1) { fprintf(stderr, "Could not register socket, exiting."); exit(1); } /* init libev default loop */ loop = ev_default_loop(0); /* set up libev callback for incoming connections */ ev_io_init(&server_w, &server_cb, server_fd, EV_READ); ev_io_start(EV_A_ &server_w); /* ignore some signals, catch TERM with our own handler, consider using * libev for the SIGTERM callback for consistency's sake */ signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); ev_signal_init(&sigterm_w, &sigterm_cb, SIGTERM); ev_signal_start(EV_A_ &sigterm_w); /* enter main loop */ ev_run(EV_A_ 0); /* clean server state here, in case later on I decide I want to handle * SIGHUP to reboot the server without exiting the process or something */ ev_io_stop(EV_A_ &server_w); /* close socket */ close(server_fd); }
void server_run(const char* hostaddr, const int port) { struct ev_loop* mainloop = ev_default_loop(0); ev_io accept_watcher; ev_io_init(&accept_watcher, ev_io_on_request, 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); Py_END_ALLOW_THREADS }
int main(int argc, char *argv[]) { ev_io udp_watcher; struct ev_signal signal_watcher; struct ev_loop *loop; struct Peer *p; p = 0; listen_addr_len = sizeof(listen_addr); sock = socket(PF_INET, SOCK_DGRAM, 0); fcntl(sock, F_SETFL, O_NONBLOCK); bzero(&listen_addr, listen_addr_len); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(42000); listen_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr*) &listen_addr, listen_addr_len) != 0) fprintf(stderr, "could not bind\n"); if (argc == 2) { p = new_peer(); lookup(argv[1], p); p->state = CONNECTING; _connect(p); } loop = ev_default_loop(0); ev_io_init(&udp_watcher, udp_readable_cb, sock, EV_READ); ev_io_start(loop, &udp_watcher); ev_signal_init(&signal_watcher, sigint_cb, SIGINT); ev_signal_start(loop, &signal_watcher); ev_run(loop, 0); for (p = peers; p; p = p->next) die(p); return EXIT_SUCCESS; }
int event_add (struct event *ev, struct timeval *tv) { dLOOPev; if (ev->ev_events & EV_SIGNAL) { if (!ev_is_active (&ev->iosig.sig)) { ev_signal_set (&ev->iosig.sig, ev->ev_fd); ev_signal_start (EV_A_ &ev->iosig.sig); ev->ev_flags |= EVLIST_SIGNAL; } } else if (ev->ev_events & (EV_READ | EV_WRITE)) { if (!ev_is_active (&ev->iosig.io)) { ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE)); ev_io_start (EV_A_ &ev->iosig.io); ev->ev_flags |= EVLIST_INSERTED; } } if (tv) { ev->to.repeat = ev_tv_get (tv); ev_timer_again (EV_A_ &ev->to); ev->ev_flags |= EVLIST_TIMEOUT; } else { ev_timer_stop (EV_A_ &ev->to); ev->ev_flags &= ~EVLIST_TIMEOUT; } ev->ev_flags |= EVLIST_ACTIVE; return 0; }
OBJECT cpu_event_wait_signal(STATE, cpu c, OBJECT channel, int sig) { struct thread_info *ti, *tnext; OBJECT id; environment e = environment_current(); ti = (struct thread_info*)(state->thread_infos); while (ti) { tnext = ti->next; if (ti->type == SIGNAL && ti->sig == sig) { cpu tc = ti->c; STATE = ti->state; OBJECT tchan = ti->channel; _cpu_event_unregister_info(state, ti); cpu_channel_send(state, tc, tchan, Qnil); break; } ti = tnext; } /* Here is a short period during which a incoming signal would not be delivered to either an old handler or the new handler. */ ti = ALLOC_N(struct thread_info, 1); ti->fd = 0; ti->type = SIGNAL; ti->state = state; ti->c = c; ti->channel = channel; ti->sig = sig; ti->stopper = (stopper_cb)ev_signal_stop; id = _cpu_event_register_info(state, ti); THDEBUG("%d: channel for signal: %p\n", getpid(), channel); ev_signal_init(&ti->ev.signal, _cpu_wake_channel_for_signal, sig); ti->ev.signal.data = ti; ev_signal_start(e->sig_event_base, &ti->ev.signal); return id; }
int main () { ev_io io_w; ev_timer timer_w; ev_signal signal_w; struct ev_loop * loop = ev_default_loop (0); //ev_io_init (&io_w, io_action, STDIN_FILENO, EV_READ); //ev_io_start (loop, &io_w); ev_timer_init (&timer_w, timer_action, 3, 0); ev_timer_start (loop, &timer_w); ev_signal_init (&signal_w, signal_action, SIGINT); ev_signal_start (loop, &signal_w); ev_run (loop, 0); return 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 }
int main() { struct ev_loop *loop = ev_default_loop(0); ev_signal signal_watcher; ev_signal *p_signal_watcher = &signal_watcher; ev_signal_init(p_signal_watcher, sigint_cb, SIGINT); ev_signal_start(loop, &signal_watcher); void *zctx = zmq_ctx_new(); void *zsock_recv = zmq_socket(zctx, ZMQ_PULL); assert(zsock_recv!=NULL); int rc = zmq_bind(zsock_recv, "inproc://channel"); assert(rc!=-1); ev_zsock_t wz; ev_zsock_init(&wz, zsock_cb, zsock_recv, EV_READ); ev_zsock_start(loop, &wz); void *zsock_send = zmq_socket(zctx, ZMQ_PUSH); assert(zsock_send!=NULL); rc = zmq_connect(zsock_send, "inproc://channel"); assert(rc!=-1); ev_timer timeout_watcher; ev_timer *p_timeout_watcher = &timeout_watcher; ev_timer_init (p_timeout_watcher, timeout_cb, 1.0, 1.0); timeout_watcher.data = zsock_send; ev_timer_start (loop, &timeout_watcher); ev_run (loop, 0); printf("loop exited\n"); zmq_close(zsock_recv); zmq_close(zsock_send); zmq_ctx_destroy(zctx); return 0; }
static int signal_os_watch(lua_State *T, int sig) { struct sigwatcher *s; if (sigismember(&signal_sigset, sig)) goto out; /* already watched */ s = lem_xmalloc(sizeof(struct sigwatcher)); signal_watcher_init(s, sig); ev_set_priority(&s->w, EV_MAXPRI); ev_signal_start(LEM_ &s->w); ev_unref(LEM); /* watcher shouldn't keep loop alive */ sigaddset(&signal_sigset, sig); pthread_sigmask(SIG_UNBLOCK, &signal_sigset, NULL); s->next = signal_watchers; signal_watchers = s; out: lua_pushboolean(T, 1); return 1; }
int main(int argc, char **argv) { int flags; mode = READING; data_size = 0; bytes_out = 0; loop = ev_loop_new( EVBACKEND_SELECT ); start_time = ev_time(); stdout_pipe.time_waiting = 0; stdout_pipe.timer_start = -1; stdin_pipe.time_waiting = 0; stdin_pipe.timer_start = -1; /* flags = fcntl(STDIN_FILENO, F_GETFL, 0); if ( fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK | flags ) == -1 ) fprintf(stderr, "{ \"msg\": \"Could not set O_NONBLOCK on stdin\" }\n", data_size, errno); flags = fcntl(STDOUT_FILENO, F_GETFL, 0); if ( fcntl(STDOUT_FILENO, F_SETFL, O_NONBLOCK | flags ) == -1 ) fprintf(stderr, "{ \"msg\": \"Could not set O_NONBLOCK on stdout\" }\n", data_size, errno); */ ev_io_init (&stdout_pipe.watcher, stdout_callback, STDOUT_FILENO, EV_WRITE); ev_io_init (&stdin_pipe.watcher, stdin_callback, STDIN_FILENO, EV_READ); ev_io_start( loop, &stdin_pipe.watcher ); ev_timer_init (&timer, timer_callback, 2.0, 2.0); ev_timer_start (loop, &timer); ev_signal_init (&exitsig, sigint_callback, SIGINT); ev_signal_start (loop, &exitsig); print_timer(); ev_run (loop, 0); }
int main(int argc, char **argv) { const char *config_file = "/etc/sniproxy.conf"; int background_flag = 1; int max_nofiles = 65536; int opt; while ((opt = getopt(argc, argv, "fc:n:V")) != -1) { switch (opt) { case 'c': config_file = optarg; break; case 'f': /* foreground */ background_flag = 0; break; case 'n': max_nofiles = atoi(optarg); break; case 'V': printf("sniproxy %s\n", sniproxy_version); #ifdef HAVE_LIBUDNS printf("compiled with udns support\n"); #endif return EXIT_SUCCESS; default: usage(); return EXIT_FAILURE; } } config = init_config(config_file, EV_DEFAULT); if (config == NULL) { fprintf(stderr, "Unable to load %s\n", config_file); usage(); return EXIT_FAILURE; } /* ignore SIGPIPE, or it will kill us */ signal(SIGPIPE, SIG_IGN); if (background_flag) { if (config->pidfile != NULL) remove(config->pidfile); daemonize(); if (config->pidfile != NULL) write_pidfile(config->pidfile, getpid()); } start_binder(); set_limits(max_nofiles); init_listeners(&config->listeners, &config->tables, EV_DEFAULT); /* Drop permissions only when we can */ drop_perms(config->user ? config->user : default_username); ev_signal_init(&sighup_watcher, signal_cb, SIGHUP); ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1); ev_signal_init(&sigusr2_watcher, signal_cb, SIGUSR2); ev_signal_init(&sigint_watcher, signal_cb, SIGINT); ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); ev_signal_start(EV_DEFAULT, &sighup_watcher); ev_signal_start(EV_DEFAULT, &sigusr1_watcher); ev_signal_start(EV_DEFAULT, &sigusr2_watcher); ev_signal_start(EV_DEFAULT, &sigint_watcher); ev_signal_start(EV_DEFAULT, &sigterm_watcher); resolv_init(EV_DEFAULT, config->resolver.nameservers, config->resolver.search, config->resolver.mode); init_connections(); ev_run(EV_DEFAULT, 0); free_connections(EV_DEFAULT); resolv_shutdown(EV_DEFAULT); free_config(config, EV_DEFAULT); stop_binder(); return 0; }
int main(int argc, char** argv) { // Bail out early if we don't have the right argument // count, and try to tell the user not to run us // if stderr happens to be hooked up to a terminal if(argc != 5) { fprintf(stderr, "This binary is not for human execution!\n"); exit(99); } bool debug = false; if(!strcmp(argv[1], "Y")) debug = true; bool use_syslog = false; if(!strcmp(argv[2], "S")) use_syslog = true; dmn_init1(debug, true, use_syslog, "gdnsd_extmon_helper"); // Note that gdnsd_initialize() would be standard here, but extmon_helper // is special: it doesn't actually make use of most of libgdnsd, just the // very basic compiler, allocator, and libdmn logging bits. // regardless, we seal off stdin now. We don't need it, // and this way we don't have to deal with it when // execv()-ing child commands later. if(!freopen("/dev/null", "r", stdin)) dmn_log_fatal("Cannot open /dev/null: %s", dmn_logf_strerror(errno)); // Also unconditionally unset NOTIFY_SOCKET here so that children // don't get any ideas about talking to systemd on our behalf. // (we're done using it in this process for libdmn stuff at this point) unsetenv("NOTIFY_SOCKET"); // these are the main communication pipes to the daemon/plugin plugin_read_fd = atoi(argv[3]); plugin_write_fd = atoi(argv[4]); if(plugin_read_fd < 3 || plugin_read_fd > 1000 || plugin_write_fd < 3 || plugin_write_fd > 1000) log_fatal("Invalid pipe descriptors!"); if(emc_read_exact(plugin_read_fd, "HELO")) log_fatal("Failed to read HELO from plugin"); if(emc_write_string(plugin_write_fd, "HELO_ACK", 8)) log_fatal("Failed to write HELO_ACK to plugin"); uint8_t ccount_buf[7]; if(emc_read_nbytes(plugin_read_fd, 7, ccount_buf) || strncmp((char*)ccount_buf, "CMDS:", 5)) log_fatal("Failed to read command count from plugin"); num_mons = ((unsigned)ccount_buf[5] << 8) + ccount_buf[6]; if(!num_mons) log_fatal("Received command count of zero from plugin"); mons = xcalloc(num_mons, sizeof(mon_t)); if(emc_write_string(plugin_write_fd, "CMDS_ACK", 8)) log_fatal("Failed to write CMDS_ACK to plugin"); // Note, it's merely a happy coincidence that our mons[] // indices exactly match cmd->idx numbers. Always use // the cmd->idx numbers as the official index when talking // to the main daemon! for(unsigned i = 0; i < num_mons; i++) { mons[i].cmd = emc_read_command(plugin_read_fd); if(!mons[i].cmd) log_fatal("Failed to read command %u from plugin", i); if(i != mons[i].cmd->idx) log_fatal("BUG: plugin index issues, %u vs %u", i, mons[i].cmd->idx); if(emc_write_string(plugin_write_fd, "CMD_ACK", 7)) log_fatal("Failed to write CMD_ACK for command %u to plugin", i); } if(emc_read_exact(plugin_read_fd, "END_CMDS")) log_fatal("Failed to read END_CMDS from plugin"); if(emc_write_string(plugin_write_fd, "END_CMDS_ACK", 12)) log_fatal("Failed to write END_CMDS_ACK to plugin"); // done with the serial setup, close the readpipe and go nonblocking on write for eventloop... close(plugin_read_fd); if(fcntl(plugin_write_fd, F_SETFL, (fcntl(plugin_write_fd, F_GETFL, 0)) | O_NONBLOCK) == -1) log_fatal("Failed to set O_NONBLOCK on pipe: %s", dmn_logf_errno()); // CLOEXEC the write fd so child scripts can't mess with it if(fcntl(plugin_write_fd, F_SETFD, FD_CLOEXEC)) log_fatal("Failed to set FD_CLOEXEC on plugin write fd: %s", dmn_logf_strerror(errno)); // init results-sending queue sendq_init(); // Set up libev error callback ev_set_syserr_cb(&syserr_for_ev); // Construct the default loop for the main thread struct ev_loop* def_loop = ev_default_loop(EVFLAG_AUTO); if(!def_loop) log_fatal("Could not initialize the default libev loop"); // Catch SIGINT/TERM/HUP, and do not let them prevent loop exit sigterm_watcher = xmalloc(sizeof(ev_signal)); sigint_watcher = xmalloc(sizeof(ev_signal)); sighup_watcher = xmalloc(sizeof(ev_signal)); ev_signal_init(sigterm_watcher, sig_cb, SIGTERM); ev_signal_init(sigint_watcher, sig_cb, SIGINT); ev_signal_init(sighup_watcher, sig_cb, SIGHUP); ev_signal_start(def_loop, sigterm_watcher); ev_signal_start(def_loop, sigint_watcher); ev_signal_start(def_loop, sighup_watcher); ev_unref(def_loop); ev_unref(def_loop); ev_unref(def_loop); // set up primary read/write watchers on the pipe to the daemon's plugin plugin_write_watcher = xmalloc(sizeof(ev_io)); ev_io_init(plugin_write_watcher, plugin_write_cb, plugin_write_fd, EV_WRITE); ev_set_priority(plugin_write_watcher, 1); // set up interval watchers for each monitor, initially for immediate firing // for the daemon's monitoring init cycle, then repeating every interval. for(unsigned i = 0; i < num_mons; i++) { mon_t* this_mon = &mons[i]; this_mon->interval_timer = xmalloc(sizeof(ev_timer)); ev_timer_init(this_mon->interval_timer, mon_interval_cb, 0., this_mon->cmd->interval); this_mon->interval_timer->data = this_mon; ev_set_priority(this_mon->interval_timer, 0); ev_timer_start(def_loop, this_mon->interval_timer); // initialize the other watchers in the mon_t here as well, // but do not start them (the interval callback starts them each interval) this_mon->cmd_timeout = xmalloc(sizeof(ev_timer)); ev_timer_init(this_mon->cmd_timeout, mon_timeout_cb, 0, 0); ev_set_priority(this_mon->cmd_timeout, -1); this_mon->cmd_timeout->data = this_mon; this_mon->child_watcher = xmalloc(sizeof(ev_child)); ev_child_init(this_mon->child_watcher, mon_child_cb, 0, 0); this_mon->child_watcher->data = this_mon; } log_info("gdnsd_extmon_helper running"); ev_run(def_loop, 0); // graceful shutdown should have cleared out children, but // the hard kill/wait below is for (a) ungraceful shutdown // on unexpected pipe close and (b) anything else going wrong // during graceful shutdown. bool needs_wait = false; for(unsigned i = 0; i < num_mons; i++) { if(mons[i].cmd_pid) { log_debug("not-so-graceful shutdown: sending SIGKILL to %li", (long)mons[i].cmd_pid); kill(mons[i].cmd_pid, SIGKILL); needs_wait = true; } } if(needs_wait) { unsigned i = 500; // 5s for OS to give us all the SIGKILL'd zombies while(i--) { pid_t wprv = waitpid(-1, NULL, WNOHANG); if(wprv < 0) { if(errno == ECHILD) break; else log_fatal("waitpid(-1, NULL, WNOHANG) failed: %s", dmn_logf_errno()); } if(wprv) log_debug("not-so-graceful shutdown: waitpid reaped %li", (long)wprv); const struct timespec ms_10 = { 0, 10000000 }; nanosleep(&ms_10, NULL); } } // Bye! if(killed_by) { log_info("gdnsd_extmon_helper exiting gracefully due to signal %i", killed_by); #ifdef COVERTEST_EXIT exit(0); #else raise(killed_by); #endif } else { log_info("gdnsd_extmon_helper exiting un-gracefully"); exit(42); } }
int main(int argc, char **argv) { int i, c; int pid_flags = 0; char *user = NULL; char *local_port = NULL; char *local_addr = NULL; char *password = NULL; char *timeout = NULL; char *method = NULL; char *pid_path = NULL; char *conf_path = NULL; char *iface = NULL; srand(time(NULL)); int remote_num = 0; ss_addr_t remote_addr[MAX_REMOTE_NUM]; char *remote_port = NULL; int option_index = 0; static struct option long_options[] = { { "fast-open", no_argument, 0, 0 }, { "acl", required_argument, 0, 0 }, { 0, 0, 0, 0 } }; opterr = 0; while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:i:c:b:a:uv", long_options, &option_index)) != -1) { switch (c) { case 0: if (option_index == 0) { fast_open = 1; } else if (option_index == 1) { LOGD("initialize acl..."); acl = !init_acl(optarg); } break; case 's': remote_addr[remote_num].host = optarg; remote_addr[remote_num++].port = NULL; break; case 'p': remote_port = optarg; break; case 'l': local_port = optarg; break; case 'k': password = optarg; break; case 'f': pid_flags = 1; pid_path = optarg; break; case 't': timeout = optarg; break; case 'm': method = optarg; break; case 'c': conf_path = optarg; break; case 'i': iface = optarg; break; case 'b': local_addr = optarg; break; case 'a': user = optarg; break; case 'u': udprelay = 1; break; case 'v': verbose = 1; break; } } if (opterr) { usage(); exit(EXIT_FAILURE); } if (conf_path != NULL) { jconf_t *conf = read_jconf(conf_path); if (remote_num == 0) { remote_num = conf->remote_num; for (i = 0; i < remote_num; i++) { remote_addr[i] = conf->remote_addr[i]; } } if (remote_port == NULL) { remote_port = conf->remote_port; } if (local_addr == NULL) { local_addr = conf->local_addr; } if (local_port == NULL) { local_port = conf->local_port; } if (password == NULL) { password = conf->password; } if (method == NULL) { method = conf->method; } if (timeout == NULL) { timeout = conf->timeout; } if (fast_open == 0) { fast_open = conf->fast_open; } #ifdef HAVE_SETRLIMIT if (nofile == 0) { nofile = conf->nofile; } /* * no need to check the return value here since we will show * the user an error message if setrlimit(2) fails */ if (nofile) { if (verbose) { LOGD("setting NOFILE to %d", nofile); } set_nofile(nofile); } #endif } if (remote_num == 0 || remote_port == NULL || local_port == NULL || password == NULL) { usage(); exit(EXIT_FAILURE); } if (timeout == NULL) { timeout = "10"; } if (local_addr == NULL) { local_addr = "0.0.0.0"; } if (pid_flags) { USE_SYSLOG(argv[0]); daemonize(pid_path); } if (fast_open == 1) { #ifdef TCP_FASTOPEN LOGD("using tcp fast open"); #else LOGE("tcp fast open is not supported by this environment"); #endif } #ifdef __MINGW32__ winsock_init(); #else // ignore SIGPIPE signal(SIGPIPE, SIG_IGN); signal(SIGABRT, SIG_IGN); #endif struct ev_signal sigint_watcher; struct ev_signal sigterm_watcher; ev_signal_init(&sigint_watcher, signal_cb, SIGINT); ev_signal_init(&sigterm_watcher, signal_cb, SIGTERM); ev_signal_start(EV_DEFAULT, &sigint_watcher); ev_signal_start(EV_DEFAULT, &sigterm_watcher); // Setup keys LOGD("initialize ciphers... %s", method); int m = enc_init(password, method); // Setup socket int listenfd; listenfd = create_and_bind(local_addr, local_port); if (listenfd < 0) { FATAL("bind() error.."); } if (listen(listenfd, SOMAXCONN) == -1) { FATAL("listen() error."); } setnonblocking(listenfd); LOGD("server listening at port %s.", local_port); // Setup proxy context struct listen_ctx listen_ctx; listen_ctx.remote_num = remote_num; listen_ctx.remote_addr = malloc(sizeof(ss_addr_t) * remote_num); while (remote_num > 0) { int index = --remote_num; if (remote_addr[index].port == NULL) { remote_addr[index].port = remote_port; } listen_ctx.remote_addr[index] = remote_addr[index]; } listen_ctx.timeout = atoi(timeout); listen_ctx.fd = listenfd; listen_ctx.iface = iface; listen_ctx.method = m; struct ev_loop *loop = EV_DEFAULT; if (!loop) { FATAL("ev_loop error."); } ev_io_init(&listen_ctx.io, accept_cb, listenfd, EV_READ); ev_io_start(loop, &listen_ctx.io); // Setup UDP if (udprelay) { LOGD("udprelay enabled."); init_udprelay(local_addr, local_port, remote_addr[0].host, remote_addr[0].port, m, listen_ctx.timeout, iface); } // setuid if (user != NULL) { run_as(user); } // Init connections cork_dllist_init(&connections); // Enter the loop ev_run(loop, 0); if (verbose) { LOGD("closed nicely."); } // Clean up free_connections(loop); free_udprelay(); ev_io_stop(loop, &listen_ctx.io); free(listen_ctx.remote_addr); #ifdef __MINGW32__ winsock_cleanup(); #endif ev_signal_stop(EV_DEFAULT, &sigint_watcher); ev_signal_stop(EV_DEFAULT, &sigterm_watcher); return 0; }