Shut down if we lose a LightProcess child

This should only happen if there's a bug in our code and the
child process crashes, or if one gets killed by the OOM killer. In
either case, it's probably not safe for the parent process to continue
uninterrupted, so shut down.
Esse commit está contido em:
bsimmers
2013-04-11 14:18:59 -07:00
commit de Sara Golemon
commit 547a45231d
4 arquivos alterados com 53 adições e 2 exclusões
+11 -2
Ver Arquivo
@@ -925,8 +925,17 @@ static int execute_program_impl(int argc, char **argv) {
open_server_log_file();
// Defer the initialization of light processes until the log file handle
// is created, so that light processes can log to the right place.
// Defer the initialization of light processes until the log file handle is
// created, so that light processes can log to the right place. If we ever
// lose a light process, stop the server instead of proceeding in an
// uncertain state.
LightProcess::SetLostChildHandler([](pid_t child) {
if (!HttpServer::Server) return;
if (!HttpServer::Server->isStopped()) {
Logger::Warning("Lost light process child %ld. Stopping server.", child);
HttpServer::Server->stop();
}
});
LightProcess::Initialize(RuntimeOption::LightProcessFilePrefix,
RuntimeOption::LightProcessCount,
inherited_fds);
@@ -264,6 +264,8 @@ void AdminRequestHandler::handleRequest(Transport *transport) {
if (cmd == "stop") {
transport->sendString("OK\n");
Logger::Info("Got admin port stop request from %s",
transport->getRemoteHost());
HttpServer::Server->stop();
break;
}
+36
Ver Arquivo
@@ -280,6 +280,8 @@ static void do_change_user(FILE *fin, FILE *fout) {
static boost::scoped_array<LightProcess> g_procs;
static int g_procsCount = 0;
static bool s_handlerInited = false;
static LightProcess::LostChildHandler s_lostChildHandler;
LightProcess::LightProcess()
: m_shadowProcess(0), m_fin(nullptr), m_fout(nullptr), m_afdt_fd(-1),
@@ -288,6 +290,24 @@ LightProcess::LightProcess()
LightProcess::~LightProcess() {
}
void LightProcess::SigChldHandler(int sig, siginfo_t* info, void* ctx) {
if (info->si_code != CLD_EXITED &&
info->si_code != CLD_KILLED &&
info->si_code != CLD_DUMPED) {
return;
}
pid_t pid = info->si_pid;
for (int i = 0; i < g_procsCount; ++i) {
if (g_procs[i].m_shadowProcess == pid) {
// The exited process was a light process. Notify the callback, if any.
if (s_lostChildHandler) {
s_lostChildHandler(pid);
}
break;
}
}
}
void LightProcess::Initialize(const std::string &prefix, int count,
const vector<int> &inherited_fds) {
if (prefix.empty() || count <= 0) {
@@ -299,6 +319,18 @@ void LightProcess::Initialize(const std::string &prefix, int count,
return;
}
if (!s_handlerInited) {
struct sigaction sa;
struct sigaction old_sa;
sa.sa_sigaction = &LightProcess::SigChldHandler;
sa.sa_flags = SA_SIGINFO | SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, &old_sa) != 0) {
Logger::Error("Couldn't install SIGCHLD handler");
abort();
}
s_handlerInited = true;
}
g_procs.reset(new LightProcess[count]);
g_procsCount = count;
@@ -682,5 +714,9 @@ void LightProcess::ChangeUser(const string &username) {
}
}
void LightProcess::SetLostChildHandler(const LostChildHandler& handler) {
s_lostChildHandler = handler;
}
///////////////////////////////////////////////////////////////////////////////
}
+4
Ver Arquivo
@@ -37,6 +37,9 @@ public:
const std::vector<int> &inherited_fds);
static void ChangeUser(const std::string &username);
typedef std::function<void(pid_t)> LostChildHandler;
static void SetLostChildHandler(const LostChildHandler& handler);
static FILE *popen(const char *cmd, const char *type,
const char *cwd = nullptr);
static int pclose(FILE *f);
@@ -66,6 +69,7 @@ public:
private:
static int GetId();
static void SigChldHandler(int sig, siginfo_t* info, void* ctx);
bool initShadow(const std::string &prefix, int id,
const std::vector<int> &inherited_fds);