void MSWindowsWatchdog::startProcess() { if (m_command.empty()) { throw XMSWindowsWatchdogError("cannot start process, command is empty"); } m_commandChanged = false; if (m_processRunning) { LOG((CLOG_DEBUG "closing existing process to make way for new one")); shutdownProcess(m_processInfo.hProcess, m_processInfo.dwProcessId, 20); m_processRunning = false; } m_session.updateActiveSession(); SECURITY_ATTRIBUTES sa; ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); getActiveDesktop(&sa); ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); HANDLE userToken = getUserToken(&sa); m_autoElevated = false; // patch by Jack Zhou and Henry Tung // set UIAccess to fix Windows 8 GUI interaction // http://synergy-project.org/spit/issues/details/3338/#c70 DWORD uiAccess = 1; SetTokenInformation(userToken, TokenUIAccess, &uiAccess, sizeof(DWORD)); BOOL createRet = doStartProcess(m_command, userToken, &sa); if (!createRet) { LOG((CLOG_ERR "could not launch")); DWORD exitCode = 0; GetExitCodeProcess(m_processInfo.hProcess, &exitCode); LOG((CLOG_ERR "exit code: %d", exitCode)); throw XArch(new XArchEvalWindows); } else { // wait for program to fail. ARCH->sleep(1); if (!isProcessActive()) { throw XMSWindowsWatchdogError("process immediately stopped"); } m_processRunning = true; m_processFailures = 0; LOG((CLOG_DEBUG "started process, session=%i, command=%s", m_session.getActiveSessionId(), m_command.c_str())); } }
bool ZoneAdminRpcMethod::duplicateProcess(const char* command, XmlRpcResponse& response, ExecutionStatus& status ) { bool result = false; if (isProcessActive(command)) { // process already found running. set found to true. UtlString faultMsg; faultMsg.append("Duplicate process '"); faultMsg.append(command); faultMsg.append("' found"); response.setFault(ZoneAdminRpcMethod::DuplicateInstance, faultMsg.data()); status = XmlRpcMethod::FAILED; result = true; } return result; }
void MSWindowsWatchdog::mainLoop(void*) { shutdownExistingProcesses(); SendSas sendSasFunc = NULL; HINSTANCE sasLib = LoadLibrary("sas.dll"); if (sasLib) { LOG((CLOG_DEBUG "found sas.dll")); sendSasFunc = (SendSas)GetProcAddress(sasLib, "SendSAS"); } SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; if (!CreatePipe(&m_stdOutRead, &m_stdOutWrite, &saAttr, 0)) { throw XArch(new XArchEvalWindows()); } ZeroMemory(&m_processInfo, sizeof(PROCESS_INFORMATION)); while (m_monitoring) { try { if (m_processRunning && getCommand().empty()) { LOG((CLOG_INFO "process started but command is empty, shutting down")); shutdownExistingProcesses(); m_processRunning = false; continue; } if (m_processFailures != 0) { // increasing backoff period, maximum of 10 seconds. int timeout = (m_processFailures * 2) < 10 ? (m_processFailures * 2) : 10; LOG((CLOG_INFO "backing off, wait=%ds, failures=%d", timeout, m_processFailures)); ARCH->sleep(timeout); } if (!getCommand().empty() && ((m_processFailures != 0) || m_session.hasChanged() || m_commandChanged)) { startProcess(); } if (m_processRunning && !isProcessActive()) { m_processFailures++; m_processRunning = false; LOG((CLOG_WARN "detected application not running, pid=%d", m_processInfo.dwProcessId)); } if (sendSasFunc != NULL) { HANDLE sendSasEvent = CreateEvent(NULL, FALSE, FALSE, "Global\\SendSAS"); if (sendSasEvent != NULL) { // use SendSAS event to wait for next session (timeout 1 second). if (WaitForSingleObject(sendSasEvent, 1000) == WAIT_OBJECT_0) { LOG((CLOG_DEBUG "calling SendSAS")); sendSasFunc(FALSE); } CloseHandle(sendSasEvent); continue; } } // if the sas event failed, wait by sleeping. ARCH->sleep(1); } catch (std::exception& e) { LOG((CLOG_ERR "failed to launch, error: %s", e.what())); m_processFailures++; m_processRunning = false; continue; } catch (...) { LOG((CLOG_ERR "failed to launch, unknown error.")); m_processFailures++; m_processRunning = false; continue; } } if (m_processRunning) { LOG((CLOG_DEBUG "terminated running process on exit")); shutdownProcess(m_processInfo.hProcess, m_processInfo.dwProcessId, 20); } LOG((CLOG_DEBUG "watchdog main thread finished")); }
bool SwAdminRpcExecStatus::execute(const HttpRequestContext& requestContext, UtlSList& params, void* userData, XmlRpcResponse& response, ExecutionStatus& status) { bool result = false; status = XmlRpcMethod::FAILED; if (2 != params.entries()) { handleExtraExecuteParam(name(), response, status); } else { if (!params.at(0) || !params.at(0)->isInstanceOf(UtlString::TYPE)) { handleMissingExecuteParam(name(), PARAM_NAME_CALLING_HOST, response, status); } else { UtlString* pCallingHostname = dynamic_cast<UtlString*>(params.at(0)); SipxRpc* pSipxRpcImpl = ((SipxRpc *)userData); if (!params.at(1) || !params.at(1)->isInstanceOf(UtlString::TYPE)) { handleMissingExecuteParam(name(), PARAM_NAME_COMMAND, response, status); } else { if (validCaller(requestContext, *pCallingHostname, response, *pSipxRpcImpl, name())) { UtlString* query = dynamic_cast<UtlString*>(params.at(1)); UtlString processName; // Make sure that the query is valid if (isQueryValid(*query, processName)) { UtlString stat; if (isProcessActive(processName)) { stat = PROCESS_RUNNING; } else { stat = PROCESS_NOT_RUNNING; } response.setResponse(&stat); status = XmlRpcMethod::OK; result = true; } // wrong Query String else { // Failed to launch the command, send a fault. response.setFault(SwAdminRpcMethod::FailureToLaunch, "Invalid query"); status = XmlRpcMethod::FAILED; } } // validcaller else { status = XmlRpcMethod::FAILED; } } // param 1 okay } // param 0 okay } //number of parms check return result; }