// This gets it's own thread, and polls the client once per second to see if // there is a signal, i.e., if the user has pressed Ctrl-C, etc. If there is a // signal, it is passed as an interrupt to the proxy in an attempt to get other // threads in the sandbox to stop. // // If another thread in the sandbox fails to stop and consume the signal then // it will be passed to the dummy sandbox instead. void DebuggerProxy::pollSignal() { TRACE(2, "DebuggerProxy::pollSignal\n"); while (!m_stopped) { sleep(1); // after 1 second that no active thread picks up the signal, we send it // to dummy sandbox if (m_signum != CmdSignal::SignalNone && m_dummySandbox) { Lock lock(m_signumMutex); if (m_signum != CmdSignal::SignalNone) { m_dummySandbox->notifySignal(m_signum); m_signum = CmdSignal::SignalNone; } } Lock lock(m_signalMutex); // Send CmdSignal over to the client and wait for a response. CmdSignal cmd; if (!cmd.onServer(this)) break; // on socket error DebuggerCommandPtr res; while (!DebuggerCommand::Receive(m_thrift, res, "DebuggerProxy::pollSignal()")) { // We will wait forever until DebuggerClient sends us something. } if (!res) break; CmdSignalPtr sig = dynamic_pointer_cast<CmdSignal>(res); if (!sig) { Logger::Error("bad response from signal polling: %d", res->getType()); break; } m_signum = sig->getSignal(); if (m_signum != CmdSignal::SignalNone) { Debugger::RequestInterrupt(shared_from_this()); } } }
// This gets it's own thread, and polls the client once per second to see if // there is a signal, i.e., if the user has pressed Ctrl-C, etc. If there is a // signal, it is passed as an interrupt to the proxy in an attempt to get other // threads in the sandbox to stop. // // If another thread in the sandbox fails to stop and consume the signal then // it will be passed to the dummy sandbox instead. void DebuggerProxy::pollSignal() { TRACE_RB(2, "DebuggerProxy::pollSignal: starting\n"); int signalTimeout = RuntimeOption::DebuggerSignalTimeout; while (!m_stopped) { sleep(1); // Block any threads that might be interrupting from communicating with the // client until we're done with this poll. Lock lock(m_signalMutex); // After DebuggerSignalTimeout seconds that no active thread picks // up the signal, we send it to dummy sandbox. if ((m_signum != CmdSignal::SignalNone) && m_dummySandbox && (--signalTimeout <= 0)) { TRACE_RB(2, "DebuggerProxy::pollSignal: sending to dummy sandbox\n"); m_dummySandbox->notifySignal(m_signum); m_signum = CmdSignal::SignalNone; } // Don't actually poll if another thread is already in a command // processing loop with the client. if (!m_okayToPoll) continue; // Send CmdSignal over to the client and wait for a response. CmdSignal cmd; if (!cmd.onServer(*this)) { TRACE_RB(2, "DebuggerProxy::pollSignal: " "Failed to send CmdSignal to client\n"); break; } // We've sent the client a command, and we expect an immediate // response. Wait 10 times to give it a chance on especially // overloaded computers. DebuggerCommandPtr res; for (int i = 0; i < 10; i++) { if (DebuggerCommand::Receive(m_thrift, res, "DebuggerProxy::pollSignal()")) break; if (m_stopped) { TRACE_RB(2, "DebuggerProxy::pollSignal: " "signal thread asked to stop while waiting " "for CmdSignal back from the client\n"); break; } } if (!res) { if (!m_stopped) { TRACE_RB(2, "DebuggerProxy::pollSignal: " "Failed to get CmdSignal back from client\n"); } break; } CmdSignalPtr sig = dynamic_pointer_cast<CmdSignal>(res); if (!sig) { TRACE_RB(2, "DebuggerProxy::pollSignal: " "bad response from signal polling: %d", res->getType()); break; } auto newSignum = sig->getSignal(); if (newSignum != CmdSignal::SignalNone) { TRACE_RB(2, "DebuggerProxy::pollSignal: " "got interrupt signal from client\n"); m_signum = newSignum; signalTimeout = RuntimeOption::DebuggerSignalTimeout; Debugger::RequestInterrupt(shared_from_this()); } } if (!m_stopped) { // We've noticed that the socket has closed. Stop and destory this proxy. TRACE_RB(2, "DebuggerProxy::pollSignal: " "lost communication with the client, stopping proxy\n"); Debugger::UsageLog("server", getSandboxId(), "ProxyError", "Signal poll"); stop(); } TRACE_RB(2, "DebuggerProxy::pollSignal: ended\n"); }