void ph_panic(const char *fmt, ...) { va_list ap; va_start(ap, fmt); ph_logv(PH_LOG_PANIC, fmt, ap); va_end(ap); ph_log(PH_LOG_PANIC, "Fatal error detected at:"); ph_log_stacktrace(PH_LOG_PANIC); abort(); }
ph_result_t ph_nbio_emitter_apply_io_mask( struct ph_nbio_emitter *emitter, ph_job_t *job, ph_iomask_t mask) { struct epoll_event evt; int res; int want_mask; if (job->fd == -1) { return PH_OK; } switch (mask & (PH_IOMASK_READ|PH_IOMASK_WRITE)) { case PH_IOMASK_READ|PH_IOMASK_WRITE: want_mask = EPOLLIN|EPOLLOUT|DEFAULT_POLL_MASK; break; case PH_IOMASK_READ: want_mask = EPOLLIN|DEFAULT_POLL_MASK; break; case PH_IOMASK_WRITE: want_mask = EPOLLOUT|DEFAULT_POLL_MASK; break; case 0: default: want_mask = 0; break; } if (want_mask == 0) { job->mask = 0; job->kmask = 0; res = epoll_ctl(emitter->io_fd, EPOLL_CTL_DEL, job->fd, &evt); if (res < 0 && errno == ENOENT) { res = 0; } } else { int op = job->kmask ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; evt.events = want_mask; evt.data.ptr = job; // Set the masks on the job before we epoll_ctl as it // may arrive at another thread *before* epoll_ctl returns job->kmask = want_mask; job->mask = mask; res = epoll_ctl(emitter->io_fd, op, job->fd, &evt); if (res == -1 && errno == EEXIST && op == EPOLL_CTL_ADD) { // This can happen when we're transitioning between distinct job // pointers, for instance, when we're moving from an async connect // to setting up the sock job res = epoll_ctl(emitter->io_fd, EPOLL_CTL_MOD, job->fd, &evt); } else if (res == -1 && errno == ENOENT && op == EPOLL_CTL_MOD) { res = epoll_ctl(emitter->io_fd, EPOLL_CTL_ADD, job->fd, &evt); } if (res == -1 && errno == EEXIST) { res = 0; } } if (res == -1) { ph_log(PH_LOG_ERR, "fd=%d (callback=%p) epoll_ctl: setting mask to %02x -> %d `Pe%d", job->fd, (void*)(uintptr_t)job->callback, mask, errno, errno); ph_log_stacktrace(PH_LOG_ERR); return PH_ERR; } return PH_OK; }