inline void courtesy_yield(void) { if (0 == epoll_wait(ribs_epoll_fd, &last_epollev, 1, 0)) return; queue_current_ctx(); ribs_swapcurcontext(epoll_worker_get_last_context()); }
static void _handle_sig_child(void) { struct signalfd_siginfo sfd_info; for (;;yield()) { for (;;) { ssize_t res = read(sigfd, &sfd_info, sizeof(struct signalfd_siginfo)); if (0 > res) { if (errno != EAGAIN) LOGGER_PERROR("read from signal fd"); break; } if (sizeof(struct signalfd_siginfo) != res) { LOGGER_ERROR("failed to read from signal fd, incorrect size"); continue; } memset(&last_sig_info, 0, sizeof(last_sig_info)); epoll_worker_ignore_events(sigfd); for (;;) { last_sig_info.si_pid = 0; if (0 > waitid(P_ALL, 0, &last_sig_info, WEXITED | WNOHANG) && ECHILD != errno) { LOGGER_PERROR("waitid"); break; } pid_t pid = last_sig_info.si_pid; if (0 == pid) break; /* no more events */ if (logger_pid == pid) { char fname[256]; snprintf(fname, sizeof(fname), "%s-%d.crash.log", program_invocation_short_name, getpid()); fname[sizeof(fname)-1] = 0; int fd = creat(fname, 0644); if (0 <= fd) { dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); LOGGER_ERROR("logger [%d] terminated unexpectedly: %s, status=%d", pid, _get_exit_reason(&last_sig_info), last_sig_info.si_status); } epoll_worker_exit(); } int i; for (i = 0; i < num_instances-1; ++i) { /* check if it is our pid */ if (children_pids[i] == pid) { children_pids[i] = 0; /* mark pid as handled */ LOGGER_ERROR("child process [%d] terminated unexpectedly: %s, status=%d", pid, _get_exit_reason(&last_sig_info), last_sig_info.si_status); epoll_worker_exit(); } } uint32_t loc = hashtable_lookup(&ht_pid_to_ctx, &pid, sizeof(pid)); if (0 == loc) { LOGGER_ERROR("unhandled SIGCHLD detected, exiting..."); epoll_worker_exit(); } else { if (0 > queue_current_ctx()) { LOGGER_ERROR("failed to queue current context, exiting..."); return epoll_worker_exit(); } struct ribs_context *ctx = *(struct ribs_context **)hashtable_get_val(&ht_pid_to_ctx, loc); hashtable_remove(&ht_pid_to_ctx, &pid, sizeof(pid)); ribs_swapcurcontext(ctx); } } epoll_worker_resume_events(sigfd); } } }