📄 fatcontroller.cpp
字号:
} catch (exception& e) {} _exit(rc); // baby go bye bye } else { // must be parent close(sv[1]); addChild(getChildSlot(), sv[0], child_pid); #ifdef DGDEBUG std::cout << "Preforked parent added child to list" << std::endl; #endif } } return 1; // parent returning}void FatController::tidyUpForChild() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_DFL; if (sigaction(SIGTERM, &sa, NULL)) { // restore sig handler // in child process #ifdef DGDEBUG std::cerr << "Error resetting signal for SIGTERM" << std::endl; #endif syslog(LOG_ERR, "%s","Error resetting signal for SIGTERM"); } memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; if (sigaction(SIGUSR1, &sa, NULL)) { // restore sig handler // in child process #ifdef DGDEBUG std::cerr << "Error resetting signal for SIGUSR1" << std::endl; #endif syslog(LOG_ERR, "%s","Error resetting signal for SIGUSR1"); } memset(&sa, 0, sizeof(sa)); sa.sa_handler = &sig_hup; if (sigaction(SIGHUP, &sa, NULL)) { // restore sig handler // in child process #ifdef DGDEBUG std::cerr << "Error resetting signal for SIGHUP" << std::endl; #endif syslog(LOG_ERR, "%s","Error resetting signal for SIGHUP"); } // now close open socket pairs don't need for (int i = 0; i < o.max_children; i++) { if (pids[i + 1].fd != -1) { try { close(pids[i + 1].fd); } catch (exception& e) {} } } delete[] childrenpids; delete[] childrenstates; delete[] pids; // 3 deletes good, memory leaks bad}int FatController::handleConnections(int pipe) { ConnectionHandler h; // the class that handles the connections String ip; bool toldparentready = false; int cycle = o.maxage_children; int stat = 0; reloadconfig = false; while(cycle-- && !reloadconfig) { if (!toldparentready) { if (sendReadyStatus(pipe) == -1) { // non-blocking (timed) #ifdef DGDEBUG std::cout << "parent timed out telling it we're ready" << std::endl; #endif break; // parent timed out telling it we're ready // so either parent gone or problem so lets exit this joint } toldparentready = true; } if (!getFDFromParent(pipe)) {// blocks waiting for a few mins continue; } toldparentready = false; if (peersockfd < 1 || peersockip.length() < 7) { continue; } h.handleConnection(peersockfd, peersockip, peersockport); // deal with the connection close(peersockfd); } #ifdef DGDEBUG if (reloadconfig) { std::cout << "child been told to exit by hup" << std::endl; } #endif if (!toldparentready) { stat = 2; } return stat;}int FatController::getChildSlot() { int i; for(i = 0; i < o.max_children; i++) { if (childrenpids[i] == -1) { return i; } } return -1;}void FatController::addChild(int pos, int fd, pid_t child_pid) { childrenpids[pos] = (int)child_pid; childrenstates[pos] = 4; // busy waiting for init numchildren++; busychildren++; waitingfor++; pids[pos + 1].fd = fd;}void FatController::cullChildren(int num) { #ifdef DGDEBUG cout << "culling childs:" << num << endl; #endif int i; int count = 0; for(i = o.max_children - 1; i >= 0; i--) { if (childrenstates[i] == 0) { kill(childrenpids[i], SIGTERM); count++; childrenstates[i] = -2; // dieing numchildren--; try { close(pids[i + 1].fd); } catch (exception& e) {} pids[i + 1].fd = -1; if (count >= num) { break; } } }}void FatController::killAllChildren() { #ifdef DGDEBUG cout << "killing all childs:" << endl; #endif for(int i = o.max_children - 1; i >= 0; i--) { if (childrenstates[i] >= 0) { kill(childrenpids[i], SIGTERM); childrenstates[i] = -2; // dieing numchildren--; } }}void FatController::hupAllChildren() { #ifdef DGDEBUG cout << "huping all childs:" << endl; #endif for(int i = o.max_children - 1; i >= 0; i--) { if (childrenstates[i] >= 0) { kill(childrenpids[i], SIGHUP); } }}bool FatController::checkKidReadyStatus(int tofind) { bool found = false; char* buf = new char[5]; int rc = -1; // for compiler warnings for(int f = 1; f <= o.max_children; f++) { if (tofind < 1) { break; // no point looping through all if all found } if (pids[f].fd == -1) { continue; } if ((pids[f].revents & POLLIN) > 0) { if (childrenstates[f - 1] < 0) { tofind--; continue; } try { rc = getLineFromFD(pids[f].fd, buf, 4, 100); } catch (exception& e) { kill(childrenpids[f - 1], SIGTERM); deleteChild(childrenpids[f - 1], -1); tofind--; continue; } if (rc > 0) { if (buf[0] == '2') { if (childrenstates[f - 1] == 4) { waitingfor--; } childrenstates[f - 1] = 0; busychildren--; tofind--; } } else { // child -> parent communications failure so kill it kill(childrenpids[f - 1], SIGTERM); deleteChild(childrenpids[f - 1], -1); tofind--; } } if (childrenstates[f - 1] == 0) { found = true; } } // if unbusy found then true otherwise false delete[] buf; return found;}void FatController::deleteChild(int child_pid, int stat) { int i; for(i = 0; i < o.max_children; i++) { if (childrenpids[i] == child_pid) { childrenpids[i] = -1; if (childrenstates[i] == 1) { if (stat == 2) { busychildren--; } else { busychildren--; // should only happen if kid goes screwy } } if (childrenstates[i] != -2) { // -2 is when its been culled numchildren--; // so no need to duplicate try { close(pids[i + 1].fd); // closing etc } catch (exception& e) {} pids[i + 1].fd = -1; } childrenstates[i] = -1; // unused break; } } // never should happen that passed pid not know // unless its the logger or url cache process in which case we} // don't want to do anything anyway and this can only happen // when shutting down or restartingint FatController::getFreeChild() { // check that there is 1 free done // before calling int i; for(i = 0; i < o.max_children; i++) { if (childrenstates[i] == 0) { // not busy (free) return i; } } return -1;}int FatController::sendReadyStatus(int pipe) { // blocks until timeout String message = "2\n"; try { if (!writeToFd(pipe, message.toCharArray(), message.length(), 15)) { return -1; } } catch (exception& e) { return -1; } return 0;}void FatController::tellChildAccept(int num) { int fd = pids[num + 1].fd; String message = "G\n"; try { writeToFd(fd, message.toCharArray(), message.length(), 5); } catch (exception& e) { kill(childrenpids[num], SIGTERM); deleteChild(childrenpids[num], -1); return; } char* buf = new char[5]; try { getLineFromFD(fd, buf, 4, 5); } catch (exception& e) { kill(childrenpids[num], SIGTERM); deleteChild(childrenpids[num], -1); delete[] buf; return; } delete[] buf; // no need to check as the very fact the child sent // something back is a good sign busychildren++; childrenstates[num] = 1; // busy}bool FatController::getFDFromParent(int fd) { String message; char* buf = new char[5]; int rc; try { rc = getLineFromFD(fd, buf, 4, 360); // blocks for a few mins } catch (exception& e) { delete[] buf; reloadconfig = true; return false; } // that way if child does nothing for a long time it will eventually // exit reducing the forkpool depending on o.maxage_children which is // usually 500 so max time a child hangs around is lonngggg // it needs to be a long block to stop the machine needing to page in // the process if (rc < 1) { delete[] buf; return false; } if (buf[0] != 'G') { delete[] buf; return false; } delete[] buf; sockaddr_in peer_adr_inet; socklen_t peer_adr_inet_length = sizeof(struct sockaddr_in); // OS X defines accept as: // int accept(int s, struct sockaddr *addr, int *addrlen); // but everyone else as: // int accept(int s, struct sockaddr *addr, socklen_t *addrlen);#ifdef __DARWIN peersockfd = accept(serversock.getFD(), (struct sockaddr *) &peer_adr_inet, (int *)&peer_adr_inet_length);#else peersockfd = accept(serversock.getFD(), (struct sockaddr *) &peer_adr_inet, &peer_adr_inet_length);#endif peersockip = inet_ntoa(peer_adr_inet.sin_addr); peersockport = ntohs(peer_adr_inet.sin_port); // get the new socket which // describes the accepted connection try { writeToFd(fd, "K\n", 2, 10); // need to make parent wait for OK // so effectively providing a lock } catch (exception& e) { try { close(peersockfd); } catch (exception& e) { } return false; } if (peersock.getFD() < 1) { if (o.logconerror == 1) { syslog(LOG_INFO, "%s","Error accepting. (Ignorable)"); } return false; } return true;}bool FatController::writeToFd(int fd, const char* buff, int len, int timeout) { int actuallysent = 0; int sent; while (actuallysent < len) { if (!readyForOutput(fd, timeout)) { return false; } sent = send(fd, buff + actuallysent, len - actuallysent, 0); if (sent < 0) { if (errno == EINTR && !reloadconfig) { continue; // was interupted by signal so restart } return false; } if (sent == 0) { return false; // other end is closed } actuallysent += sent; } return true;}bool FatController::readyForOutput(int fd, int timeout) { fd_set fdSet; FD_ZERO(&fdSet); // clear the set FD_SET(fd, &fdSet); // add fd to the set
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -