BOOL CreateBuilderJob(PCTSTR appName, PTSTR cmdLine, PCTSTR workDir, H2BOperation& op) { BOOL ret = TRUE; DWORD err = ERROR_SUCCESS; HANDLE job = CreateJobObject(NULL, NULL); if( job ) { JOBOBJECT_BASIC_LIMIT_INFORMATION jobLimit = { }; jobLimit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS; jobLimit.ActiveProcessLimit = 1; if( SetInformationJobObject(job, JobObjectBasicLimitInformation, &jobLimit, sizeof(jobLimit)) ) { if( ! CreateBuilderProcess(job, appName, cmdLine, workDir, op) ) err = GetLastError(); } if( err == ERROR_CANCELLED ) TerminateJobObject(job, ERROR_CANCELLED); CloseHandle(job); } if( err != ERROR_SUCCESS ) { SetLastError(err); ret = FALSE; } return ret; }
void Job::waitForEvent(DWORD timeout) { gatherInfo(); testRestrictions(); DWORD evnt; ULONG key; LPOVERLAPPED lpOverlapped; BOOL reslt = GetQueuedCompletionStatus(port.handle(),&evnt,&key, &lpOverlapped,timeout); if (reslt == 0) { DWORD err = GetLastError(); tryApi(_T("GetQueuedCompletionStatus"),err == WAIT_TIMEOUT); } else { if (evnt == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) jobactive = false; else if (evnt == JOB_OBJECT_MSG_END_OF_JOB_TIME || evnt == JOB_OBJECT_MSG_END_OF_PROCESS_TIME) res = JobResult(JobResult::TL,_T("")); else if (evnt == JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT) res = JobResult(JobResult::SV, Messages::RESULT_CHILD_PROCESS); else if (evnt == JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT || evnt == JOB_OBJECT_MSG_JOB_MEMORY_LIMIT) res = JobResult(JobResult::ML,_T("")); } if (res.valid()) { tryApi(_T("TerminateJobObject"), TerminateJobObject(hJob,0) != 0); } else if (!active()) { DWORD code; tryApi(_T("GetExitCodeProcess"), GetExitCodeProcess(hMainProcess,&code) != 0); res = JobResult(JobResult::OK, _T("")); } }
void CJobObject::Terminate(DWORD dwExitCode) { CMutex::CEnter MutexEnter(m_Mutex); BOOL bRet; bRet = TerminateJobObject(GetHandle(), dwExitCode); if (bRet == 0) { throw CCodineException(CError::GetErrorMessage(GetLastError()), __FILE__, __LINE__); } }
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { AttachConsole(ATTACH_PARENT_PROCESS); // Create a named pipe that we can be signaled on for early termination wchar_t buf[512]; wsprintf(buf, L"\\\\.\\pipe\\jobber-%d", GetCurrentProcessId()); HANDLE hPipe = CreateNamedPipe(buf, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_READMODE_BYTE | PIPE_WAIT, 1, 256, 256, 100000, NULL); OVERLAPPED io = { 0 }; io.hEvent = CreateEvent(NULL, true, true, NULL); if (!ConnectNamedPipe(hPipe, &io) && GetLastError() != ERROR_IO_PENDING) { DWORD dwLastError = GetLastError(); return -1; } STARTUPINFO si = { 0 }; PROCESS_INFORMATION pi = { 0 }; si.cb = sizeof(STARTUPINFO); si.wShowWindow = nCmdShow; if (!CreateProcess(NULL, lpCmdLine, NULL, NULL, true, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { DWORD dwLastError = GetLastError(); return -1; } HANDLE hJob = CreateJobObject(NULL, NULL); AssignProcessToJobObject(hJob, pi.hProcess); ResumeThread(pi.hThread); HANDLE handles[2]; handles[0] = io.hEvent; handles[1] = pi.hProcess; int result = WaitForMultipleObjects(2, handles, false, INFINITE); TerminateJobObject(hJob, -1); if (result == WAIT_OBJECT_0) { return -1; } else { DWORD dwExit; GetExitCodeProcess(pi.hProcess, &dwExit); return dwExit; } }
void rktio_process_deinit(rktio_t *rktio) { #ifdef RKTIO_SYSTEM_WINDOWS if (rktio->process_job_object) { TerminateJobObject(rktio->process_job_object, 1); CloseHandle(rktio->process_job_object); rktio->process_job_object = NULL; } #endif #if defined(RKTIO_SYSTEM_UNIX) && !defined(CENTRALIZED_SIGCHILD) remove_from_sigchld_chain(rktio); #endif }
ActivePet::~ActivePet() { m_files->ignore(m_requestFolderPath, m_dispatcher); // Kill any stray processes. if (!TerminateJobObject(m_job.get(), -1)) { printf("TerminateJobObject() failed: %d", GetLastError()); } // TODO: Change this algorithm for transient accounts. std::for_each(m_syncers.begin(), m_syncers.end(), delete_element<Syncer*>()); RegKey editables = RegKey::HKCU.open(Constants::registryPets() + L"\\" + m_petname + L"\\" + Constants::editables()); editables.removeSubKeys(); // Unload the profile. UnloadUserProfile(m_session.get(), m_profile); // Undo the changes to the winsta0 and desktop DACLs. auto_buffer<PSID> logon_sid = GetLogonSID(m_session.get()); if (NULL == logon_sid.get()) { return; } auto_close<HWINSTA, &::CloseWindowStation> winsta0(OpenWindowStation(L"winsta0", FALSE, READ_CONTROL | WRITE_DAC)); if (NULL == winsta0.get()) { printf("OpenWindowStation() failed: %d", GetLastError()); return; } if (!RemoveAceFromWindowStation(winsta0.get(), logon_sid.get())) { printf("RemoveAceFromWindowStation() failed: %d", GetLastError()); return; } auto_close<HDESK, &::CloseDesktop> desktop(OpenDesktop(L"default", 0, FALSE, READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS)); if (NULL == desktop.get()) { printf("OpenDesktop() failed: %d", GetLastError()); return; } if (!RemoveAceFromDesktop(desktop.get(), logon_sid.get())) { printf("AddAceToDesktop() failed: %d", GetLastError()); return; } }
int run_compiler(const char *cmd, int *exit_code) { HANDLE hChild = create_child_process(cmd); if(!hChild) { return 1; } *exit_code = 0; if(WAIT_TIMEOUT == WaitForSingleObject(hChild, compiler_max_time + 200)) { *exit_code = 2; TerminateJobObject(hJOB, 1); //WaitForSingleObject(hChild, INFINITE); } if(! *exit_code) GetExitCodeProcess(hChild, (LPDWORD)exit_code); CloseHandle(hChild); CloseHandle(hJOB); return 0; }
bool JobObject::terminateJob(unsigned int exitCode) { if(m_hJobObject) { if(TerminateJobObject(m_hJobObject, exitCode)) { return true; } else { qWarning("Failed to terminate job object!"); return false; } } else { qWarning("Cannot assign process to job: No job bject available!"); return false; } }
/// <summary> /// Frees a console and closes the job </summary> /// /// <param name="ac"> /// Console object to free </param> void ImFreeConsole(INOUT IM_CONSOLE* ac) { // Close write handle first to prevent writes if (ac->hWrite != INVALID_HANDLE_VALUE && ac->hWrite != NULL) { CloseHandle(ac->hWrite); ac->hWrite = NULL; } // Then read handle if (ac->hRead != INVALID_HANDLE_VALUE && ac->hRead != NULL) { CloseHandle(ac->hRead); ac->hRead == NULL; } // Process cleanup if (ac->hChildProcess != INVALID_HANDLE_VALUE && ac->hChildProcess != NULL) { // Unnecessary as TerminateJobObject will do this for us, but it's nice to be clean TerminateProcess(ac->hChildProcess, 0); CloseHandle(ac->hChildProcess); } TerminateJobObject(ac->hJob, 0); }
/* 结束进程方案2 TerminateJobObject */ BOOL KillProcessMethod_2(DWORD dwProcessID) { BOOL bRet; HANDLE hProcess, hJob; hProcess = OpenProcess(PROCESS_SET_QUOTA | PROCESS_TERMINATE, FALSE, dwProcessID); if (hProcess == NULL) { return FALSE; } hJob = CreateJobObject(NULL, _T("TestJob")); if (!AssignProcessToJobObject(hJob, hProcess)) { return FALSE; } bRet = TerminateJobObject(hJob, 0); CloseHandle(hProcess); CloseHandle(hJob); return bRet; }
void CPCD::Process::stop() { char filename[PATH_MAX*2+1]; BaseString::snprintf(filename, sizeof(filename), "%d", m_id); unlink(filename); if (is_bad_pid(m_pid)) { logger.critical("Stopping process with bogus pid: %d id: %d", m_pid, m_id); return; } m_status = STOPPING; #ifndef _WIN32 errno = 0; int signo= SIGTERM; if(m_shutdown_options == "SIGKILL") signo= SIGKILL; int ret = kill(-m_pid, signo); switch(ret) { case 0: logger.debug("Sent SIGTERM to pid %d", (int)-m_pid); break; default: logger.debug("kill pid: %d : %s", (int)-m_pid, strerror(errno)); break; } if(isRunning()){ errno = 0; ret = kill(-m_pid, SIGKILL); switch(ret) { case 0: logger.debug("Sent SIGKILL to pid %d", (int)-m_pid); break; default: logger.debug("kill pid: %d : %s\n", (int)-m_pid, strerror(errno)); break; } } #else if(isRunning()) { BOOL truth; HANDLE proc; require(proc = OpenProcess(PROCESS_QUERY_INFORMATION, 0, m_pid)); require(IsProcessInJob(proc, m_job, &truth)); require(truth == TRUE); require(CloseHandle(proc)); // Terminate process with exit code 37 require(TerminateJobObject(m_job, 37)); require(CloseHandle(m_job)); } #endif m_pid = bad_pid; m_status = STOPPED; }
bool WindowsJob::terminate(DWORD exitCode) { return !!TerminateJobObject(jobHandle_, exitCode); }
int main(int argc, char **argv) { #ifdef WINDOWS HANDLE event; char cmdline[128]; if (argc == 1) { /* parent process */ STARTUPINFO si = { sizeof(STARTUPINFO) }; PROCESS_INFORMATION pi; HANDLE job, job2, job3; JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit = {0,}; DWORD exitcode = (DWORD)-1; /* For synchronization we create an inherited event */ SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE/*inherit*/}; event = CreateEvent(&sa, FALSE/*manual reset*/, FALSE/*start unset*/, NULL); if (event == NULL) print("Failed to create event"); _snprintf(cmdline, BUFFER_SIZE_ELEMENTS(cmdline), "%s %p", argv[0], event); print("creating child #1\n"); if (!CreateProcess(argv[0], cmdline, NULL, NULL, TRUE/*inherit handles*/, 0, NULL, NULL, &si, &pi)) print("CreateProcess failure\n"); WaitForSingleObject(event, INFINITE); print("terminating child #1 by NtTerminateProcess\n"); TerminateProcess(pi.hProcess, 42); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); print("child #1 exit code = %d\n", exitcode); if (!ResetEvent(event)) print("Failed to reset event\n"); print("creating child #2\n"); if (!CreateProcess(argv[0], cmdline, NULL, NULL, TRUE/*inherit handles*/, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) print("CreateProcess failure\n"); job = CreateJobObject(NULL, "drx-test job"); AssignProcessToJobObject(job, pi.hProcess); ResumeThread(pi.hThread); CloseHandle(pi.hThread); WaitForSingleObject(event, INFINITE); print("terminating child #2 by NtTerminateJobObject\n"); TerminateJobObject(job, 123456); CloseHandle(job); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); print("child #2 exit code = %d\n", exitcode); if (!ResetEvent(event)) print("Failed to reset event\n"); print("creating child #3\n"); if (!CreateProcess(argv[0], cmdline, NULL, NULL, TRUE/*inherit handles*/, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) print("CreateProcess failure\n"); job = CreateJobObject(NULL, "drx-test job"); AssignProcessToJobObject(job, pi.hProcess); limit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit, sizeof(limit))) print("SetInformationJobObject failed\n"); ResumeThread(pi.hThread); CloseHandle(pi.hThread); WaitForSingleObject(event, INFINITE); print("terminating child #3 by closing job handle\n"); CloseHandle(job); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); print("child #3 exit code = %d\n", exitcode); /* Test DuplicateHandle (DrMem i#1401) */ print("creating child #4\n"); if (!CreateProcess(argv[0], cmdline, NULL, NULL, TRUE/*inherit handles*/, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) print("CreateProcess failure\n"); job = CreateJobObject(NULL, "drx-test job"); AssignProcessToJobObject(job, pi.hProcess); limit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &limit, sizeof(limit))) print("SetInformationJobObject failed\n"); if (!DuplicateHandle(GetCurrentProcess(), job, GetCurrentProcess(), &job2, 0, FALSE, DUPLICATE_SAME_ACCESS)) print("DuplicateHandle failed\n"); if (!DuplicateHandle(GetCurrentProcess(), job, GetCurrentProcess(), &job3, 0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) print("DuplicateHandle failed\n"); ResumeThread(pi.hThread); CloseHandle(pi.hThread); WaitForSingleObject(event, INFINITE); print("terminating child #4 by closing both job handles\n"); CloseHandle(job2); CloseHandle(job3); WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); print("child #4 exit code = %d\n", exitcode); } else { /* child process */ int iter = 0; if (sscanf(argv[1], "%p", &event) != 1) { print("Failed to obtain event handle from %s\n", argv[1]); return -1; } if (!SetEvent(event)) print("Failed to set event\n"); /* spin until parent kills us or we time out */ while (iter++ < 12) { Sleep(5000); } } CloseHandle(event); #else /* WINDOWS */ int pipefd[2]; pid_t cpid; char buf = 0; if (pipe(pipefd) == -1) { perror("pipe"); exit(1); } print("creating child\n"); cpid = fork(); if (cpid == -1) { perror("fork"); exit(1); } else if (cpid > 0) { /* parent */ int status; close(pipefd[1]); /* close unused write end */ if (read(pipefd[0], &buf, sizeof(buf)) <= 0) { perror("pipe read failed"); exit(1); } print("terminating child by sending SIGKILL\n"); kill(cpid, SIGKILL); wait(&status); /* wait for child */ close(pipefd[0]); print("child exit code = %d\n", status); } else { /* child */ int iter = 0; close(pipefd[0]); /* close unused read end */ write(pipefd[1], &buf, sizeof(buf)); close(pipefd[1]); /* spin until parent kills us or we time out */ while (iter++ < 12) { sleep(5); } } #endif /* UNIX */ return 0; }
/****** C_Communication::DoComm() const **************************************** * NAME * C_Communication::DoComm() const -- does the communication * * SYNOPSIS * int C_Communication::DoComm() const * * FUNCTION * Does the communication with sge_shepherd. I.e. whenever a sge_shepherd * connects to the server, it receives the request, does what is requested * and then shuts down the connection. * * RESULT * int - 0 if command was successfully received and processed, 1 else * * NOTES *******************************************************************************/ int C_Communication::DoComm() const { int ret = 1; int idx = 0; SOCKET comm_sock; int remote_saddr_len; struct sockaddr_in remote_saddr; char szMessage[1024]; char command[COMMAND_SIZE]; const int commandsize = sizeof(command); C_Job Job; C_Job *pJob = NULL; en_request_type request_type; remote_saddr_len = sizeof(remote_saddr); comm_sock = accept(m_ListenSocket, (struct sockaddr*)&remote_saddr, &remote_saddr_len); if(comm_sock == INVALID_SOCKET) { return WSAGetLastError(); } ZeroMemory(command, COMMAND_SIZE); while((ret=recv(comm_sock, command+idx, commandsize-idx, 0))>0) { idx += ret; if(command[idx-1] == EOF) { break; } } if(ret == -1) { ret = WSAGetLastError(); ShutdownSocket(&comm_sock); return ret; } ret = 0; request_type = Job.ParseCommand(command); switch(request_type) { case req_job_start: POSITION Pos; HANDLE hThread; if(g_bAcceptJobs) { Job.m_comm_sock = comm_sock; sprintf(szMessage, "Starting job %lu.%lu %s", Job.m_job_id, Job.m_ja_task_id, Job.m_pe_task_id ? Job.m_pe_task_id : "<null>"); WriteToLogFile(szMessage); // try to put job in job list pJob = new C_Job(Job); Pos = g_JobList.AddJobToList(pJob); } if(Pos != NULL) { // job is not already in job list, send ACK and start worker thread hThread = CreateThread(NULL, 0, JobStarterThread, 0, 0, 0); CloseHandle(hThread); } else { // job is already in job list, send NACK and delete job object strcpy(szMessage, "NAK"); szMessage[strlen(szMessage)+1] = (char)EOF; send(comm_sock, szMessage, (int)strlen(szMessage)+2, 0); ShutdownSocket(&comm_sock); delete pJob; pJob = NULL; } break; case req_send_job_usage: pJob = g_JobList.RemoveJobFromList(Job); if(pJob) { pJob->m_comm_sock = comm_sock; SendJobUsage(*pJob); delete pJob; pJob = NULL; sprintf(szMessage, "Sending usage of job %lu.%lu %s", Job.m_job_id, Job.m_ja_task_id, Job.m_pe_task_id ? Job.m_pe_task_id : "<null>"); } else { sprintf(szMessage, "Warning: Job %lu.%lu %s not found!", Job.m_job_id, Job.m_ja_task_id, Job.m_pe_task_id ? Job.m_pe_task_id : "<null>"); } WriteToLogFile(szMessage); ShutdownSocket(&comm_sock); break; case req_forward_signal: // lock access to job list CSingleLock singleLock(&g_JobList.m_JobListMutex); singleLock.Lock(); pJob = g_JobList.FindJobInList(Job); if(pJob && pJob->m_JobStatus != js_Finished && pJob->m_JobStatus != js_Failed && pJob->m_JobStatus != js_Deleted) { BOOL bRet = FALSE; char szAnswer[100]; int sent; if(pJob->m_hProcess != INVALID_HANDLE_VALUE && pJob->m_hJobObject != INVALID_HANDLE_VALUE) { bRet = TerminateJobObject(pJob->m_hJobObject, 0); if(bRet) { pJob->m_JobStatus = js_Deleted; } } singleLock.Unlock(); sprintf(szAnswer, "%s", bRet ? "ACK" : "NAK"); szAnswer[strlen(szAnswer)+1] = (char)EOF; sent = send(comm_sock, szAnswer, (int)strlen(szAnswer)+2, 0); if(sent >= 0) { ret = 0; } } else { singleLock.Unlock(); } ShutdownSocket(&comm_sock); break; } return ret; }
/****************************************************************************** * * * Function: zbx_waitpid * * * * Purpose: this function waits for process to change state * * * * Parameters: pid - [IN] child process PID * * * * Return value: on success, PID is returned. On error, * * -1 is returned, and errno is set appropriately * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static int zbx_waitpid(pid_t pid) { const char *__function_name = "zbx_waitpid"; int rc, status; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); do { #ifdef WCONTINUED static int wcontinued = WCONTINUED; retry: if (-1 == (rc = waitpid(pid, &status, WUNTRACED | wcontinued))) { if (EINVAL == errno && 0 != wcontinued) { wcontinued = 0; goto retry; } #else if (-1 == (rc = waitpid(pid, &status, WUNTRACED))) { #endif zabbix_log(LOG_LEVEL_DEBUG, "%s() waitpid failure: %s", __function_name, zbx_strerror(errno)); goto exit; } if (WIFEXITED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() exited, status:%d", __function_name, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() killed by signal %d", __function_name, WTERMSIG(status)); else if (WIFSTOPPED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() stopped by signal %d", __function_name, WSTOPSIG(status)); #ifdef WIFCONTINUED else if (WIFCONTINUED(status)) zabbix_log(LOG_LEVEL_DEBUG, "%s() continued", __function_name); #endif } while (!WIFEXITED(status) && !WIFSIGNALED(status)); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, rc); return rc; } #endif /* _WINDOWS */ /****************************************************************************** * * * Function: zbx_execute * * * * Purpose: this function executes a script and returns result from stdout * * * * Parameters: command - [IN] command for execution * * buffer - [OUT] buffer for output, if NULL - ignored * * error - [OUT] error string if function fails * * max_error_len - [IN] length of error buffer * * * * Return value: SUCCEED if processed successfully, TIMEOUT_ERROR if * * timeout occurred or FAIL otherwise * * * * Author: Alexander Vladishev * * * ******************************************************************************/ int zbx_execute(const char *command, char **buffer, char *error, size_t max_error_len, int timeout) { size_t buf_size = PIPE_BUFFER_SIZE, offset = 0; int ret = FAIL; #ifdef _WINDOWS STARTUPINFO si; PROCESS_INFORMATION pi; SECURITY_ATTRIBUTES sa; HANDLE job = NULL, hWrite = NULL, hRead = NULL; char *cmd = NULL; wchar_t *wcmd = NULL; struct _timeb start_time, current_time; #else pid_t pid; int fd; #endif *error = '\0'; if (NULL != buffer) { *buffer = zbx_realloc(*buffer, buf_size); **buffer = '\0'; } #ifdef _WINDOWS /* set the bInheritHandle flag so pipe handles are inherited */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; /* create a pipe for the child process's STDOUT */ if (0 == CreatePipe(&hRead, &hWrite, &sa, 0)) { zbx_snprintf(error, max_error_len, "unable to create a pipe: %s", strerror_from_system(GetLastError())); goto close; } /* create a new job where the script will be executed */ if (0 == (job = CreateJobObject(&sa, NULL))) { zbx_snprintf(error, max_error_len, "unable to create a job: %s", strerror_from_system(GetLastError())); goto close; } /* fill in process startup info structure */ memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); si.hStdOutput = hWrite; si.hStdError = hWrite; /* use cmd command to support scripts */ cmd = zbx_dsprintf(cmd, "cmd /C \"%s\"", command); wcmd = zbx_utf8_to_unicode(cmd); /* create the new process */ if (0 == CreateProcess(NULL, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) { zbx_snprintf(error, max_error_len, "unable to create process [%s]: %s", cmd, strerror_from_system(GetLastError())); goto close; } CloseHandle(hWrite); hWrite = NULL; /* assign the new process to the created job */ if (0 == AssignProcessToJobObject(job, pi.hProcess)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); if (0 == TerminateProcess(pi.hProcess, 0)) { zabbix_log(LOG_LEVEL_ERR, "failed to terminate [%s]: %s", cmd, strerror_from_system(GetLastError())); } } else if (-1 == ResumeThread(pi.hThread)) { zbx_snprintf(error, max_error_len, "unable to assign process [%s] to a job: %s", cmd, strerror_from_system(GetLastError())); } else ret = SUCCEED; if (FAIL == ret) goto close; _ftime(&start_time); timeout *= 1000; ret = zbx_read_from_pipe(hRead, buffer, &buf_size, &offset, timeout); if (TIMEOUT_ERROR != ret) { _ftime(¤t_time); if (0 < (timeout -= zbx_get_timediff_ms(&start_time, ¤t_time)) && WAIT_TIMEOUT == WaitForSingleObject(pi.hProcess, timeout)) { ret = TIMEOUT_ERROR; } } CloseHandle(pi.hProcess); CloseHandle(pi.hThread); close: if (NULL != job) { /* terminate the child process and it's childs */ if (0 == TerminateJobObject(job, 0)) zabbix_log(LOG_LEVEL_ERR, "failed to terminate job [%s]: %s", cmd, strerror_from_system(GetLastError())); CloseHandle(job); } if (NULL != hWrite) CloseHandle(hWrite); if (NULL != hRead) CloseHandle(hRead); zbx_free(cmd); zbx_free(wcmd); #else /* not _WINDOWS */ alarm(timeout); if (-1 != (fd = zbx_popen(&pid, command))) { int rc; char tmp_buf[PIPE_BUFFER_SIZE]; while (0 < (rc = read(fd, tmp_buf, sizeof(tmp_buf) - 1)) && MAX_EXECUTE_OUTPUT_LEN > offset + rc) { if (NULL != buffer) { tmp_buf[rc] = '\0'; zbx_strcpy_alloc(buffer, &buf_size, &offset, tmp_buf); } } close(fd); if (-1 == rc || -1 == zbx_waitpid(pid)) { if (EINTR == errno) ret = TIMEOUT_ERROR; else zbx_snprintf(error, max_error_len, "zbx_waitpid() failed: %s", zbx_strerror(errno)); /* kill the whole process group, pid must be the leader */ if (-1 == kill(-pid, SIGTERM)) zabbix_log(LOG_LEVEL_ERR, "failed to kill [%s]: %s", command, zbx_strerror(errno)); zbx_waitpid(pid); } else if (MAX_EXECUTE_OUTPUT_LEN <= offset + rc) { zabbix_log(LOG_LEVEL_ERR, "command output exceeded limit of %d KB", MAX_EXECUTE_OUTPUT_LEN / ZBX_KIBIBYTE); } else ret = SUCCEED; } else zbx_strlcpy(error, zbx_strerror(errno), max_error_len); alarm(0); #endif /* _WINDOWS */ if (TIMEOUT_ERROR == ret) zbx_strlcpy(error, "Timeout while executing a shell script.", max_error_len); else if ('\0' != *error) zabbix_log(LOG_LEVEL_WARNING, "%s", error); if (SUCCEED != ret && NULL != buffer) zbx_free(*buffer); return ret; }
int main(){ DWORD exit_code, terminated; STARTUPINFO child_1_si; STARTUPINFO child_2_si; PROCESS_INFORMATION child_1_pi; PROCESS_INFORMATION child_2_pi; HANDLE job_handle = CreateJobObject(NULL, "job"); memset(&child_1_si, 0, sizeof(STARTUPINFO)); child_1_si.cb=sizeof(child_1_si); memset(&child_2_si, 0, sizeof(STARTUPINFO)); child_2_si.cb=sizeof(child_2_si); get_warning_alert("\nTrying to create the first child process..."); DWORD child_1_created = CreateProcess(NULL, "child.exe ChildOne GrandChildOne", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &child_1_si, &child_1_pi); if(!child_1_created){ get_error_alert("\nError on creating process / code #%ld", GetLastError()); exit(1); } get_success_alert("\nProcess created!"); get_warning_alert("\nTrying to create the second child process..."); DWORD child_2_created = CreateProcess(NULL, "child.exe ChildTwo GrandChildTwo", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &child_2_si, &child_2_pi); if(!child_2_created){ get_error_alert("\nError on creating process / code #%ld", GetLastError()); exit(1); } get_success_alert("\nProcess created!"); AssignProcessToJobObject(job_handle, child_2_pi.hProcess); for(int i = 0; i <= 20; i++){ get_error_alert("Parent: "); printf("on step %d\n", i); if(i == 7) { GetExitCodeProcess(child_1_pi.hProcess, &exit_code); terminated = TerminateProcess(child_1_pi.hProcess, (UINT) exit_code); if(!terminated) { get_error_alert("\nTerminating error %d\n", GetLastError()); } else { get_success_alert("\nThe first child process terminated\n"); } } if(i == 10) { GetExitCodeProcess(job_handle, &exit_code); terminated = TerminateJobObject(job_handle, (UINT) exit_code); if(!terminated) { get_error_alert("\nJob terminating error %d\n", GetLastError()); } else { get_success_alert("\nJob terminated\n"); } } Sleep(3000); } return 0; }
int main() { int argc; wchar_t ** argv = CommandLineToArgvW(GetCommandLine(), &argc); // Make sure that we've been passed the right number of arguments if (argc < 8) { _tprintf(_T("Usage: %s (four inheritable event handles) (CommandLineToSpawn)\n"), argv[0]); return(0); } // Construct the full command line int nCmdLineLength= MAX_CMD_LINE_LENGTH; wchar_t * szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t)); szCmdLine[0]= 0; int nPos = 0; for(int i = 8; i < argc; ++i) { int nCpyLen; int len= wcslen(argv[i]); int requiredSize= nPos+len+2; if (requiredSize > 32*1024) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Command line too long!\n")); #endif return 0; } ensureSize(&szCmdLine, &nCmdLineLength, requiredSize); if (NULL == szCmdLine) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Not enough memory to build cmd line!\n")); #endif return 0; } if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], len, nCmdLineLength - nPos))) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Not enough space to build command line\n")); #endif return 0; } nPos += nCpyLen; szCmdLine[nPos] = _T(' '); ++nPos; } szCmdLine[nPos] = _T('\0'); STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi = {0}; DWORD dwExitCode = 0; #ifdef DEBUG_MONITOR int currentPID = GetCurrentProcessId(); wchar_t buffer[MAX_CMD_LINE_LENGTH]; #endif BOOL exitProc = FALSE; HANDLE waitEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[4]); HANDLE h[5]; h[0] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[3]); // simulated SIGINT (CTRL-C or Cygwin 'kill -SIGINT') // h[1] we reserve for the process handle h[2] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[5]); // simulated SIGTERM h[3] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[6]); // simulated SIGKILL h[4] = OpenEventW(EVENT_ALL_ACCESS, TRUE, argv[7]); // CTRL-C, in all cases SetConsoleCtrlHandler(HandlerRoutine, TRUE); int parentPid = wcstol(argv[1], NULL, 10); int nCounter = wcstol(argv[2], NULL, 10); wchar_t inPipeName[PIPE_NAME_LENGTH]; wchar_t outPipeName[PIPE_NAME_LENGTH]; wchar_t errPipeName[PIPE_NAME_LENGTH]; swprintf(inPipeName, L"\\\\.\\pipe\\stdin%08i%010i", parentPid, nCounter); swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", parentPid, nCounter); swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", parentPid, nCounter); #ifdef DEBUG_MONITOR swprintf(buffer, _T("Pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName); OutputDebugStringW(buffer); #endif HANDLE stdHandles[3]; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFileW(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) || (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFileW(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) || (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFileW(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa)))) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Failed to open pipe %i, %i, %i: %i\n"), stdHandles[0], stdHandles[1], stdHandles[2], GetLastError()); OutputDebugStringW(buffer); #endif CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); return -1;; } SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE); SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE); if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) || !SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) || !SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Failed to reassign standard streams: %i\n"), GetLastError()); OutputDebugStringW(buffer); #endif CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); return -1;; } #ifdef DEBUG_MONITOR wchar_t * lpvEnv = GetEnvironmentStringsW(); // If the returned pointer is NULL, exit. if (lpvEnv == NULL) OutputDebugStringW(_T("Cannot Read Environment\n")); else { // Variable strings are separated by NULL byte, and the block is // terminated by a NULL byte. OutputDebugStringW(_T("Starter: Environment\n")); for (wchar_t * lpszVariable = (wchar_t *) lpvEnv; *lpszVariable; lpszVariable+=wcslen(lpszVariable) + 1) { swprintf(buffer, _T("%s\n"), lpszVariable); OutputDebugStringW(buffer); } FreeEnvironmentStringsW(lpvEnv); } #endif #ifdef DEBUG_MONITOR swprintf(buffer, _T("Starting: %s\n"), szCmdLine); OutputDebugStringW(buffer); #endif // Create job object HANDLE hJob = CreateJobObject(NULL, NULL); // Spawn the other processes as part of this Process Group BOOL f = CreateProcessW(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); // We don't need them any more CloseHandle(stdHandles[0]); CloseHandle(stdHandles[1]); CloseHandle(stdHandles[2]); if (f) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Process %i started\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif SetEvent(waitEvent); // Means thar process has been spawned CloseHandle(pi.hThread); h[1] = pi.hProcess; if(NULL != hJob) { if(!AssignProcessToJobObject(hJob, pi.hProcess)) { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Cannot assign process %i to a job\n"), pi.dwProcessId); OutputDebugStringW(buffer); DisplayErrorMessage(); #endif } } while(!exitProc) { // Wait for the spawned-process to die or for the event // indicating that the processes should be forcibly killed. DWORD event = WaitForMultipleObjects(5, h, FALSE, INFINITE); switch (event) { case WAIT_OBJECT_0 + 0: // SIGINT case WAIT_OBJECT_0 + 4: // CTRL-C #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter (PID %i) received CTRL-C event\n"), currentPID); OutputDebugStringW(buffer); #endif if ((event == (WAIT_OBJECT_0 + 0)) && isCygwin(h[1])) { // Need to issue a kill command wchar_t kill[1024]; swprintf(kill, L"kill -SIGINT %d", pi.dwProcessId); if (!runCygwinCommand(kill)) { // fall back to console event GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } } else { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } SetEvent(waitEvent); break; case WAIT_OBJECT_0 + 1: // App terminated normally // Make it's exit code our exit code #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter: launched process has been terminated(PID %i)\n"), pi.dwProcessId); OutputDebugStringW(buffer); #endif GetExitCodeProcess(pi.hProcess, &dwExitCode); exitProc = TRUE; break; // Terminate and Kill behavior differ only for cygwin processes, where // we use the cygwin 'kill' command. We send a SIGKILL in one case, // SIGTERM in the other. For non-cygwin processes, both requests // are treated exactly the same case WAIT_OBJECT_0 + 2: // TERM case WAIT_OBJECT_0 + 3: // KILL { const wchar_t* signal = (event == WAIT_OBJECT_0 + 2) ? L"TERM" : L"KILL"; #ifdef DEBUG_MONITOR swprintf(buffer, _T("starter received %s event (PID %i)\n"), signal, currentPID); OutputDebugStringW(buffer); #endif if (isCygwin(h[1])) { // Need to issue a kill command wchar_t kill[1024]; swprintf(kill, L"kill -%s %d", signal, pi.dwProcessId); if (!runCygwinCommand(kill)) { // fall back to console event GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } } else { GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); } SetEvent(waitEvent); if(NULL != hJob) { if(!TerminateJobObject(hJob, (DWORD)-1)) { #ifdef DEBUG_MONITOR OutputDebugStringW(_T("Cannot terminate job\n")); DisplayErrorMessage(); #endif } } // Note that we keep trucking until the child process terminates (case WAIT_OBJECT_0 + 1) break; } default: // Unexpected code #ifdef DEBUG_MONITOR DisplayErrorMessage(); #endif exitProc = TRUE; break; } } } else { #ifdef DEBUG_MONITOR swprintf(buffer, _T("Cannot start: %s\n"), szCmdLine); OutputDebugStringW(buffer); DisplayErrorMessage(); #endif } if (NULL != szCmdLine) { free(szCmdLine); } CloseHandle(waitEvent); CloseHandle(h[0]); CloseHandle(h[1]); CloseHandle(h[2]); CloseHandle(h[3]); CloseHandle(h[4]); return(dwExitCode); }
//终止作业 bool ZJobObject::terminate(DWORD exitCode/* = 4*/) { return !!TerminateJobObject(m_handle, exitCode); }