void Handler_task(void *v) { int rc = 0; int i = 0; Handler *handler = (Handler *)v; HandlerParser *parser = NULL; int max_targets = Setting_get_int("limits.handler_targets", 128); log_info("MAX allowing limits.handler_targets=%d", max_targets); parser = HandlerParser_create(max_targets); check_mem(parser); check(Handler_setup(handler) == 0, "Failed to initialize handler, exiting."); while(handler->running && !task_was_signaled()) { taskstate("delivering"); rc = handler_recv_parse(handler, parser); if(task_was_signaled()) { log_warn("Handler task signaled, exiting."); break; } else if( rc == -1 || parser->target_count <= 0) { log_warn("Skipped invalid message from handler: %s", bdata(handler->send_spec)); taskdelay(100); continue; } else { for(i = 0; i < (int)parser->target_count; i++) { int id = (int)parser->targets[i]; int fd = Register_fd_for_id(id); Connection *conn = fd == -1 ? NULL : Register_fd_exists(fd); // don't bother calling process request if there's nothing to handle if(conn && fd >= 0) { handler_process_request(handler, id, fd, conn, parser->body); } else { // TODO: I believe we need to notify the connection that it is dead too Handler_notify_leave(handler, id); } } } HandlerParser_reset(parser); } handler->running = 0; handler->task = NULL; HandlerParser_destroy(parser); taskexit(0); error: log_err("HANDLER TASK DIED: %s", bdata(handler->send_spec)); handler->running = 0; handler->task = NULL; HandlerParser_destroy(parser); taskexit(1); }
int _wait(void *socket, int fd, int rw) { startfdtask(); check(socket != NULL || fd >= 0, "Attempt to wait on a dead socket/fd: %p or %d", socket, fd); int max = 0; int hot_add = SuperPoll_active_hot(POLL) < SuperPoll_max_hot(POLL); int was_registered = 0; if(socket != NULL) { taskstate(rw == 'r' ? "read handler" : "write handler"); } else { was_registered = Register_fd_exists(fd) != NULL; taskstate(rw == 'r' ? "read fd" : "write fd"); } max = SuperPoll_add(POLL, (void *)taskrunning, socket, fd, rw, hot_add); check(max != -1, "Error adding fd: %d or socket: %p to task wait list.", fd, socket); taskswitch(); if(task_was_signaled()) { debug("GOT SIGNAL %d AFTER WAIT", taskrunning->signal); SuperPoll_del(POLL, socket, fd, hot_add); return -1; } if(was_registered && Register_fd_exists(fd) == NULL) { debug("Socket %d was closed after a wait.", fd); return -1; } else { return 0; } error: return -1; }
void tickertask(void *v) { (void)v; taskname("ticker"); while(!task_was_signaled()) { THE_CURRENT_TIME_IS = time(NULL); int min_wait = Setting_get_int("limits.tick_timer", 10); taskdelay(min_wait * 1000); // avoid doing this during a reload attempt if(!RELOAD) { // don't bother if these are all 0 int min_ping = Setting_get_int("limits.min_ping", DEFAULT_MIN_PING); int min_write_rate = Setting_get_int("limits.min_write_rate", DEFAULT_MIN_READ_RATE); int min_read_rate = Setting_get_int("limits.min_read_rate", DEFAULT_MIN_WRITE_RATE); if(min_ping > 0 || min_write_rate > 0 || min_read_rate > 0) { int cleared = Register_cleanout(); if(cleared > 0) { log_warn("Timeout task killed %d tasks, waiting %d seconds for more.", cleared, min_wait); } else { debug("No connections timed out."); } } // do a server queue cleanup to get rid of dead servers Server_queue_cleanup(); } } }
static inline void fdtask_shutdown() { int i = 0; for(i = 0; i < SuperPoll_active_hot(POLL); i++) { SuperPoll_compact_down(POLL, i); } // move all our sleeping tasks over to the main runqueue Task *t = NULL; while((t = sleeping.head)){ deltask(&sleeping, t); tasksignal(t, task_was_signaled()); } }
void fdtask(void *v) { int i, ms; PollResult result; int rc = 0; FDTASK = taskself(); rc = PollResult_init(POLL, &result); check(rc == 0, "Failed to initialize the poll result."); tasksystem(); taskname("fdtask"); for(;;){ /* let everyone else run */ while(taskyield() > 0) ; /* we're the only one runnable - poll for i/o */ errno = 0; taskstate("poll"); ms = next_task_sleeptime(500); if(task_was_signaled()) { fdtask_shutdown(); task_clear_signal(); break; } else { rc = SuperPoll_poll(POLL, &result, ms); check(rc != -1, "SuperPoll failure, aborting."); for(i = 0; i < rc; i++) { taskready(result.hits[i].data); } wake_sleepers(); } } PollResult_clean(&result); FDTASK = NULL; return; error: taskexitall(1); }