/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One */ #include #include "plb.h" #include "plb_globals.h" #ifdef WITH_DMALLOC # include #endif void cleanup_connect_ready(int evfd, short event, void *cleaned_server_) { Server * const cleaned_server = (Server *) cleaned_server_; plb_log(LL_DEBUG, "Starting async cleanup"); (void) evfd; if (cleaned_server->cleanup_fd == -1) { return; } if (event == EV_WRITE) { ssize_t written; while ((written = write(cleaned_server->cleanup_fd, "", (size_t) 1U)) != 1U && errno == EINTR); if (written == (ssize_t) 1U) { cleaned_server->status = 1U; plb_log(LL_WARNING, "Bringing [%s] back to life", cleaned_server->name); } else { plb_log(LL_DEBUG, "[%s] probe failure", cleaned_server->name); } } while (close(cleaned_server->cleanup_fd) != 0 && errno == EINTR); cleaned_server->cleanup_fd = -1; } void spawn_cleanup(Server * const cleaned_server) { int cleanup_fd; if (cleaned_server->cleanup_fd != -1) { plb_log(LL_DEBUG, "Cleanup already in progress, fd=[%d]", cleaned_server->cleanup_fd); return; } cleaned_server->cleanup_fd = -1; if ((cleanup_fd = socket(cleaned_server->ai_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { plb_log(LL_WARNING, "Unable to create a cleanup socket : [%s]", strerror(errno)); return; } setsockopt_aggressive(cleanup_fd); socket_nonblock(cleanup_fd); for (;;) { if (connect(cleanup_fd, (struct sockaddr *) &cleaned_server->ai_addr, (socklen_t) cleaned_server->ai_addrlen) != 0 && errno != EINPROGRESS) { if (errno == EINTR) { continue; } plb_log(LL_NOTIFY, "Cleanup socket didn't connect() : [%s]", strerror(errno)); while (close(cleanup_fd) != 0 && errno == EINTR); return; } break; } cleaned_server->cleanup_fd = cleanup_fd; plb_log(LL_DEBUG, "Should spawn async health checking fd:[%d]", cleanup_fd); event_set(&cleaned_server->cleanup_ev, cleanup_fd, EV_WRITE | EV_TIMEOUT, cleanup_connect_ready, cleaned_server); event_add(&cleaned_server->cleanup_ev, &timeout_header_server_write); } void periodic_cleanup(int dummy, const short event, void *ev) { register Server *cleaned_server; (void) dummy; (void) event; if ((cleaned_server = serverpool_head) == NULL) { plb_log(LL_ERROR, "No server pool"); return; } do { if (cleaned_server->status <= 0U) { spawn_cleanup(cleaned_server); } } while ((cleaned_server = cleaned_server->next) != NULL); evtimer_add((struct event *) ev, &timeout_cleanup); }