/* Set up a helper connection to parent using getenv() */ mowgli_eventloop_helper_proc_t * mowgli_helper_setup(mowgli_eventloop_t *eventloop) { mowgli_eventloop_helper_proc_t *helper; const char *env_io_fd; env_io_fd = getenv("IO_FD"); /* this shouldn't be a hard-fail because some idiot may run the helper from * the cmdline. allow the helper to error out gracefully if not spawned as * a helper. */ if (env_io_fd == NULL) return NULL; helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t)); helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER; helper->eventloop = eventloop; helper->fd = atoi(env_io_fd); helper->pfd = mowgli_pollable_create(helper->eventloop, helper->fd, helper); mowgli_pollable_set_nonblocking(helper->pfd, true); return helper; }
int main(void) { mowgli_eventloop_t *evloop = mowgli_eventloop_create(); mowgli_dns_t *dns = mowgli_dns_create(evloop, MOWGLI_DNS_TYPE_ASYNC); mowgli_eventloop_pollable_t *stdin_pollable = mowgli_pollable_create(evloop, STDIN_FILENO, dns); mowgli_pollable_set_nonblocking(stdin_pollable, true); mowgli_pollable_setselect(evloop, stdin_pollable, MOWGLI_EVENTLOOP_IO_READ, read_data); mowgli_eventloop_run(evloop); mowgli_eventloop_destroy(evloop); return 0; }
mowgli_eventloop_helper_proc_t * mowgli_helper_create(mowgli_eventloop_t *eventloop, mowgli_eventloop_helper_start_fn_t *start_fn, const char *helpername, void *userdata) { mowgli_eventloop_helper_proc_t *helper; mowgli_helper_create_req_t child; int io_fd[2]; return_val_if_fail(eventloop != NULL, NULL); return_val_if_fail(start_fn != NULL, NULL); child.start_fn = start_fn; child.userdata = userdata; helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t)); helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER; helper->eventloop = eventloop; socketpair(AF_UNIX, SOCK_STREAM, 0, io_fd); /* set up helper/child fd mapping */ helper->fd = io_fd[0]; child.fd = io_fd[1]; /* make pollables and make them non-blocking */ helper->pfd = mowgli_pollable_create(eventloop, helper->fd, helper); mowgli_pollable_set_nonblocking(helper->pfd, true); /* spawn helper process using mowgli_process_clone() */ helper->child = mowgli_process_clone((mowgli_process_start_fn_t) mowgli_helper_trampoline, helpername, &child); if (helper->child == NULL) { mowgli_pollable_destroy(eventloop, helper->pfd); close(io_fd[0]); close(io_fd[1]); mowgli_free(helper); return NULL; } close(child.fd); return helper; }
static void mowgli_helper_trampoline(mowgli_helper_create_req_t *req) { mowgli_eventloop_helper_proc_t *helper; #ifndef _WIN32 int i, x; #endif return_if_fail(req != NULL); return_if_fail(req->start_fn != NULL); helper = mowgli_alloc(sizeof(mowgli_eventloop_helper_proc_t)); helper->type.type = MOWGLI_EVENTLOOP_TYPE_HELPER; helper->fd = req->fd; #ifndef _WIN32 for (i = 0; i < 1024; i++) { if (i != req->fd) close(i); } x = open("/dev/null", O_RDWR); for (i = 0; i < 2; i++) { if (req->fd != i) dup2(x, i); } if (x > 2) close(x); #endif helper->eventloop = mowgli_eventloop_create(); helper->pfd = mowgli_pollable_create(helper->eventloop, helper->fd, helper); helper->userdata = req->userdata; mowgli_pollable_set_nonblocking(helper->pfd, true); req->start_fn(helper, helper->userdata); }
mowgli_eventloop_pollable_t* irc_connect(const char * host, const char * port) { mowgli_eventloop_pollable_t* out; mowgli_descriptor_t fd; struct addrinfo hints, *res; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; getaddrinfo(host, port, &hints, &res); fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); connect(fd, res->ai_addr, res->ai_addrlen); out = mowgli_pollable_create(base_eventloop, fd, NULL); mowgli_pollable_set_nonblocking(out, true); mowgli_pollable_setselect(base_eventloop, out, MOWGLI_EVENTLOOP_POLL_READ, irc_read); return out; }