void death_queue_kill(struct death_queue *dq, struct lwan_connection *conn) { death_queue_remove(dq, conn); if (LIKELY(conn->coro)) { coro_free(conn->coro); conn->coro = NULL; } if (conn->flags & CONN_IS_ALIVE) { conn->flags &= ~CONN_IS_ALIVE; close(lwan_connection_get_fd(dq->lwan, conn)); } }
static ALWAYS_INLINE void destroy_coro(struct death_queue_t *dq, lwan_connection_t *conn) { death_queue_remove(dq, conn); if (LIKELY(conn->coro)) { coro_free(conn->coro); conn->coro = NULL; } if (conn->flags & CONN_IS_ALIVE) { conn->flags &= ~CONN_IS_ALIVE; close(lwan_connection_get_fd(dq->lwan, conn)); } }
struct lwan_fd_watch *lwan_watch_fd(struct lwan *l, int fd, uint32_t events, coro_function_t coro_fn, void *data) { struct lwan_fd_watch *watch; watch = malloc(sizeof(*watch)); if (!watch) return NULL; watch->coro = coro_new(&l->switcher, coro_fn, data); if (!watch->coro) goto out; struct epoll_event ev = {.events = events, .data.ptr = watch->coro}; if (epoll_ctl(l->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { coro_free(watch->coro); goto out; } watch->fd = fd; return watch; out: free(watch); return NULL; } void lwan_unwatch_fd(struct lwan *l, struct lwan_fd_watch *w) { if (l->main_socket != w->fd) { if (epoll_ctl(l->epfd, EPOLL_CTL_DEL, w->fd, NULL) < 0) lwan_status_perror("Could not unwatch fd %d", w->fd); } coro_free(w->coro); free(w); } void lwan_main_loop(struct lwan *l) { struct epoll_event evs[16]; struct lwan_fd_watch *watch; assert(main_socket == -1); main_socket = l->main_socket; if (signal(SIGINT, sigint_handler) == SIG_ERR) lwan_status_critical("Could not set signal handler"); watch = lwan_watch_fd(l, l->main_socket, EPOLLIN | EPOLLHUP | EPOLLRDHUP, accept_connection_coro, l); if (!watch) lwan_status_critical("Could not watch main socket"); lwan_status_info("Ready to serve"); while (true) { int n_evs = epoll_wait(l->epfd, evs, N_ELEMENTS(evs), -1); if (UNLIKELY(n_evs < 0)) { if (main_socket < 0) break; if (errno == EINTR || errno == EAGAIN) continue; break; } for (int i = 0; i < n_evs; i++) { if (!coro_resume_value(evs[i].data.ptr, (int)evs[i].events)) break; } } lwan_unwatch_fd(l, watch); } #ifdef CLOCK_MONOTONIC_COARSE __attribute__((constructor)) static void detect_fastest_monotonic_clock(void) { struct timespec ts; if (!clock_gettime(CLOCK_MONOTONIC_COARSE, &ts)) monotonic_clock_id = CLOCK_MONOTONIC_COARSE; } #endif void lwan_set_thread_name(const char *name) { char thread_name[16]; char process_name[PATH_MAX]; char *tmp; int ret; if (proc_pidpath(getpid(), process_name, sizeof(process_name)) < 0) return; tmp = strrchr(process_name, '/'); if (!tmp) return; ret = snprintf(thread_name, sizeof(thread_name), "%s %s", tmp + 1, name); if (ret < 0) return; pthread_set_name_np(pthread_self(), thread_name); }