static void cleanupAgentsInBackground(vector<AgentWatcher *> &watchers) { this_thread::disable_interruption di; this_thread::disable_syscall_interruption dsi; pid_t pid; int e; pid = fork(); if (pid == 0) { // Child vector<AgentWatcher *>::const_iterator it; Timer timer(false); fd_set fds, fds2; int max, agentProcessesDone; unsigned long long deadline = 30000; // miliseconds // Wait until all agent processes have exited. max = 0; FD_ZERO(&fds); for (it = watchers.begin(); it != watchers.end(); it++) { FD_SET((*it)->getFeedbackFd(), &fds); if ((*it)->getFeedbackFd() > max) { max = (*it)->getFeedbackFd(); } } timer.start(); agentProcessesDone = 0; while (agentProcessesDone != -1 && agentProcessesDone < (int) watchers.size() && timer.elapsed() < deadline) { struct timeval timeout; #ifdef FD_COPY FD_COPY(&fds, &fds2); #else FD_ZERO(&fds2); for (it = watchers.begin(); it != watchers.end(); it++) { FD_SET((*it)->getFeedbackFd(), &fds2); } #endif timeout.tv_sec = 0; timeout.tv_usec = 10000; agentProcessesDone = syscalls::select(max + 1, &fds2, NULL, NULL, &timeout); if (agentProcessesDone > 0 && timer.elapsed() < deadline) { usleep(10000); } } if (agentProcessesDone == -1 || timer.elapsed() >= deadline) { // An error occurred or we've waited long enough. Kill all the // processes. P_WARN("Some Phusion Passenger agent processes did not exit " << "in time, forcefully shutting down all."); for (it = watchers.begin(); it != watchers.end(); it++) { (*it)->forceShutdown(); } } else { P_DEBUG("All Phusion Passenger agent processes have exited."); } // Now clean up the server instance directory. delete generation.get(); delete serverInstanceDir.get(); _exit(0); } else if (pid == -1) { // Error e = errno; throw SystemException("fork() failed", errno); } else { // Parent // Let child process handle cleanup. serverInstanceDir->detach(); generation->detach(); } }