static void pipe_to_context(void) { void *ctx; while (1) { if (sizeof(&ctx) != read(last_epollev.data.fd, &ctx, sizeof(&ctx))) { LOGGER_PERROR("read in pipe_to_context"); yield(); } else ribs_swapcurcontext(ctx); } }
static void sigrtmin_to_context(void) { struct signalfd_siginfo siginfo; while (1) { int res = read(last_epollev.data.fd, &siginfo, sizeof(struct signalfd_siginfo)); if (sizeof(struct signalfd_siginfo) != res || NULL == (void *)siginfo.ssi_ptr) { LOGGER_PERROR("sigrtmin_to_ctx got NULL or < 128 bytes: %d", res); yield(); } else ribs_swapcurcontext((void *)siginfo.ssi_ptr); } }
static void http_server_idle_handler(void) { struct http_server *server = (struct http_server *)current_ctx->data.ptr; for (;;) { if (last_epollev.events == EPOLLOUT) yield(); else { struct ribs_context *new_ctx = ctx_pool_get(&server->ctx_pool); ribs_makecontext(new_ctx, &main_ctx, http_server_fiber_main_wrapper); int fd = last_epollev.data.fd; new_ctx->fd = fd; new_ctx->data.ptr = server; struct epoll_worker_fd_data *fd_data = epoll_worker_fd_map + fd; fd_data->ctx = new_ctx; TIMEOUT_HANDLER_REMOVE_FD_DATA(fd_data); ribs_swapcurcontext(new_ctx); } } }
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()); }
inline void yield(void) { while(0 >= epoll_wait(ribs_epoll_fd, &last_epollev, 1, -1)); ribs_swapcurcontext(epoll_worker_get_last_context()); }
void epoll_worker_exit(void) { ribs_swapcurcontext(&main_ctx); }
void epoll_worker_loop(void) { ribs_swapcurcontext(event_loop_ctx); }
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); } } }