Example #1
3
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;
}
Example #2
0
File: Job.cpp Project: stden/IJE
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(""));
    }
}
Example #3
0
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__);
   }
}
Example #4
0
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;
	}

}
Example #5
0
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;
	}
}
Example #7
0
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;
}
Example #8
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;
	}
}
Example #9
0
/// <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);
}
Example #10
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;
}
Example #11
0
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);
}
Example #13
0
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;
}
Example #14
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;
}
Example #15
0
/******************************************************************************
 *                                                                            *
 * 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(&current_time);
		if (0 < (timeout -= zbx_get_timediff_ms(&start_time, &current_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;
}
Example #16
0
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;
}
Example #17
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);
}