Example #1
0
void CJobPool::WorkerThread(void *pUser)
{
	CJobPool *pPool = (CJobPool *)pUser;

	while(1)
	{
		CJob *pJob = 0;

		// fetch job from queue
		lock_wait(pPool->m_Lock);
		if(pPool->m_pFirstJob)
		{
			pJob = pPool->m_pFirstJob;
			pPool->m_pFirstJob = pPool->m_pFirstJob->m_pNext;
			if(pPool->m_pFirstJob)
				pPool->m_pFirstJob->m_pPrev = 0;
			else
				pPool->m_pLastJob = 0;
		}
		lock_unlock(pPool->m_Lock);

		// do the job if we have one
		if(pJob)
		{
			pJob->m_Status = CJob::STATE_RUNNING;
			pJob->m_Result = pJob->m_pfnFunc(pJob->m_pFuncData);
			pJob->m_Status = CJob::STATE_DONE;
		}
		else
			thread_sleep(10);
	}

}
Example #2
0
void CThreadPool::threadFunc() {
    CMutexLocker guard(m_mutex);
    // m_num_threads was already increased
    m_num_idle++;

    while (true) {
        while (m_jobs.empty()) {
            if (!threadNeeded()) break;
            m_cond.wait(m_mutex);
        }
        if (!threadNeeded()) break;

        // Figure out a job to do
        CJob* job = m_jobs.front();
        m_jobs.pop_front();

        // Now do the actual job
        m_num_idle--;
        job->m_eState = CJob::RUNNING;
        guard.unlock();

        job->runThread();

        guard.lock();
        jobDone(job);
        m_num_idle++;
    }
    assert(m_num_threads > 0 && m_num_idle > 0);
    m_num_threads--;
    m_num_idle--;

    if (m_num_threads == 0 && m_done) m_exit_cond.notify_one();
}
Example #3
0
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) 
{
   switch (id) {
      case IDCANCEL:
         // User is terminating our app, kill the job too.
         KillTimer(hwnd, 1);
         g_job.Terminate(0);  
         EndDialog(hwnd, id);
         break;

      case IDC_PERJOBUSERTIMELIMIT:
         {
         // The job time must be reset if setting a job time limit
         BOOL f;
         GetDlgItemInt(hwnd, IDC_PERJOBUSERTIMELIMIT, &f, FALSE);
         EnableWindow(
            GetDlgItem(hwnd, IDC_PRESERVEJOBTIMEWHENAPPLYINGLIMITS), !f);
         }
         break;

      case IDC_APPLYLIMITS:
         Dlg_ApplyLimits(hwnd);
         PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
         break;

      case IDC_TERMINATE:
         g_job.Terminate(0);  
         PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
         break;

      case IDC_SPAWNCMDINJOB:
         {
         // Spawn a command shell and place it in the job
         STARTUPINFO si = { sizeof(si) };
         PROCESS_INFORMATION pi;
         TCHAR sz[] = TEXT("CMD");
         CreateProcess(NULL, sz, NULL, NULL, 
            FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
         g_job.AssignProcess(pi.hProcess);
         ResumeThread(pi.hThread);
         CloseHandle(pi.hProcess);
         CloseHandle(pi.hThread);
         }
         PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
         break;

      case IDC_ASSIGNPROCESSTOJOB:
         {
         DWORD dwProcessId = GetDlgItemInt(hwnd, IDC_PROCESSID, NULL, FALSE);
         HANDLE hProcess = OpenProcess(
            PROCESS_SET_QUOTA | PROCESS_TERMINATE, FALSE, dwProcessId);
         if (hProcess != NULL) {
            chVERIFY(g_job.AssignProcess(hProcess));
            CloseHandle(hProcess);
         } else chMB("Could not assign process to job.");
         }
         PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_STATUS, NULL);
         break;
   }
}
int CCommProxy::SendJobsToRemote(vector<CJob*> &vJobs)
{
    CJob *pJob = NULL;
    char *dataBuf = NULL;
    int  bufSize = 0;
    vector<string> vSerializedJobs;
    for(vector<CJob*>::iterator iter = vJobs.begin(); iter != vJobs.end(); ++iter)
    {
        pJob = *iter;
        pJob->Serialize(&dataBuf,bufSize);
        if(m_pConfig->compress)
        {
            vector<uint8_t> compress_out;
            compress_buffer(dataBuf,bufSize,compress_out);
            delete dataBuf; //delete original bufffer
            dataBuf = (char *)&compress_out[0]; //address of the vec buffer
            bufSize = compress_out.size(); //compressed size
            string strData(dataBuf,bufSize);
            vSerializedJobs.push_back(strData);
        }
        else
        {
            string strData(dataBuf,bufSize);
            vSerializedJobs.push_back(strData);
            delete dataBuf;
        }
        delete pJob;
    }
    pClient->SendJobsToRemote(vSerializedJobs.size(),vSerializedJobs);
    return SUCCESS;
}
Example #5
0
//---------------------------------------------------------------------------
//	@function:
//		CJobFactory::PjCreate
//
//	@doc:
//		Create job of specific type
//
//---------------------------------------------------------------------------
CJob *
CJobFactory::PjCreate
	(
	CJob::EJobType ejt
	)
{
	CJob *pj = NULL;

	switch (ejt)
	{
		case CJob::EjtTest:
			pj = PtRetrieve<CJobTest>(m_pspjTest);
			break;

		case CJob::EjtGroupOptimization:
			pj = PtRetrieve<CJobGroupOptimization>(m_pspjGroupOptimization);
			break;

		case CJob::EjtGroupImplementation:
			pj = PtRetrieve<CJobGroupImplementation>(m_pspjGroupImplementation);
			break;

		case CJob::EjtGroupExploration:
			pj = PtRetrieve<CJobGroupExploration>(m_pspjGroupExploration);
			break;

		case CJob::EjtGroupExpressionOptimization:
			pj = PtRetrieve<CJobGroupExpressionOptimization>(m_pspjGroupExpressionOptimization);
			break;

		case CJob::EjtGroupExpressionImplementation:
			pj = PtRetrieve<CJobGroupExpressionImplementation>(m_pspjGroupExpressionImplementation);
			break;

		case CJob::EjtGroupExpressionExploration:
			pj = PtRetrieve<CJobGroupExpressionExploration>(m_pspjGroupExpressionExploration);
			break;

		case CJob::EjtTransformation:
			pj = PtRetrieve<CJobTransformation>(m_pspjTransformation);
			break;

		case CJob::EjtInvalid:
			GPOS_ASSERT(!"Invalid job type");
	}


	// prepare task
	pj->Reset();
	pj->SetJobType(ejt);

	return pj;
}
Example #6
0
//---------------------------------------------------------------------------
//	@function:
//		CScheduler::PjRetrieve
//
//	@doc:
//		Retrieve next runnable job from queue
//
//---------------------------------------------------------------------------
CJob *
CScheduler::PjRetrieve()
{
#ifdef GPOS_DEBUG
	// restrict parallelism to keep track of jobs
	CAutoMutex am(m_mutex);
	if (FTrackingJobs())
	{
		am.Lock();
	}
#endif // GPOS_DEBUG

	// retrieve runnable job from lists of waiting jobs
	SJobLink *pjl = m_listjlWaiting.Pop();
	CJob *pj = NULL;

	if (NULL != pjl)
	{
		pj = pjl->m_pj;

		GPOS_ASSERT(NULL != pj);
		GPOS_ASSERT(0 == pj->UlpRefs());

		// decrement number of queued jobs
		(void) UlpExchangeAdd(&m_ulpQueued, -1);

		// update statistics
		(void) UlpExchangeAdd(&m_ulpStatsDequeued, 1);

		// recycle job link
		m_spjl.Recycle(pjl);

#ifdef GPOS_DEBUG
		// add job to running list
		if (FTrackingJobs())
		{
			GPOS_ASSERT(CJob::EjsWaiting == pj->Ejs());

			pj->SetState(CJob::EjsRunning);
			m_listjRunning.Append(pj);
		}
#endif // GPOS_DEBUG
	}
	
	return pj;
}
	void Flush()
	{
		// Only safe to call when system is suspended
		m_mutex.Lock();
		m_nItems = 0;
		m_JobAvailableEvent.Reset();
		CJob *pJob;
		for ( int i = JP_HIGH; i >= 0; --i )
		{
			while ( m_queues[i].PopItem( &pJob ) )
			{
				pJob->Abort();
				pJob->Release();
			}
		}
		m_mutex.Unlock();
	}
int CCommProxy::SendCompletedJobsToRemote(std::vector<CJob*> &vJobs)
{
    CJob *pJob = NULL;
    char *dataBuf = NULL;
    int  bufSize = 0;
    vector<string> vSerializedJobs;
    for(vector<CJob*>::iterator iter = vJobs.begin(); iter != vJobs.end(); ++iter)
    {
        pJob = *iter;
        pJob->Serialize(&dataBuf,bufSize);
        string strData(dataBuf,bufSize);
        vSerializedJobs.push_back(strData);
        delete dataBuf;
    }
    pClient->SendCompletedJobsToRemote(vSerializedJobs.size(),vSerializedJobs);
    return SUCCESS;
}
Example #9
0
void CPVRManager::ExecutePendingJobs(void)
{
  CSingleLock lock(m_critSectionTriggers);

  while (m_pendingUpdates.size() > 0)
  {
    CJob *job = m_pendingUpdates.at(0);
    m_pendingUpdates.erase(m_pendingUpdates.begin());
    lock.Leave();

    job->DoWork();
    delete job;

    lock.Enter();
  }

  m_triggerEvent.Reset();
}
Example #10
0
void CJobWorker::Process()
{
  SetPriority( GetMinPriority() );
  while (true)
  {
    // request an item from our manager (this call is blocking)
    CJob *job = m_jobManager->GetNextJob(this);
    if (!job)
      break;

    bool success = false;
    try
    {
      success = job->DoWork();
    }
    catch (...)
    {
      CLog::Log(LOGERROR, "%s error processing job %s", __FUNCTION__, job->GetType());
    }
    m_jobManager->OnJobComplete(success, job);
  }
}
Example #11
0
//---------------------------------------------------------------------------
//	@function:
//		CScheduler::OsPrintActiveJobs
//
//	@doc:
//		Print scheduler queue
//
//---------------------------------------------------------------------------
IOstream &
CScheduler::OsPrintActiveJobs
	(
	IOstream &os
	)
{
	CAutoMutex am(m_mutex);
	am.Lock();

	os << "Scheduler - active jobs: " << std::endl << std::endl;

	os << "List of running jobs: " << std::endl;
	CJob *pj = m_listjRunning.PtFirst();
	while(NULL != pj)
	{
		pj->OsPrint(os);
		pj = m_listjRunning.PtNext(pj);
	}

	os << std::endl << "List of waiting jobs: " << std::endl;
	
	SJobLink *pjl = m_listjlWaiting.PtFirst();
	while(NULL != pjl)
	{
		pjl->m_pj->OsPrint(os);
		pjl = m_listjlWaiting.PtNext(pjl);
	}

	os << std::endl << "List of suspended jobs: " << std::endl;
	pj = m_listjSuspended.PtFirst();
	while(NULL != pj)
	{
		pj->OsPrint(os);
		pj = m_listjSuspended.PtNext(pj);
	}

	return os;
}
Example #12
0
void CPVRManagerJobQueue::ExecutePendingJobs()
{
  std::vector<CJob *> pendingUpdates;

  {
    CSingleLock lock(m_critSection);

    if (m_bStopped)
      return;

    pendingUpdates = std::move(m_pendingUpdates);
    m_triggerEvent.Reset();
  }

  CJob *job = nullptr;
  while (!pendingUpdates.empty())
  {
    job = pendingUpdates.front();
    pendingUpdates.erase(pendingUpdates.begin());

    job->DoWork();
    delete job;
  }
}
Example #13
0
int CCollector::Run()
{
    CTask* task = m_tasks.GetFirstTask();
    if(!task)
    {
        cout << "Task is NULL" << endl;
        return COLLECTOR_MISSION_ERROR_NOTASK;
    }
    CJob* job = task->GetFirstJob();

    int returnCode = 0;
    int jobStatus = job->GetJobStatus();
    switch (jobStatus)
    {
        case JOB_STATUS_READY:
        {
            returnCode = InitWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_CRAWL:
        {
            returnCode = CrawlWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_MATCH_RULE:
        {
            returnCode = MatchRule();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_PARSE:
        {
            returnCode = ParseWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_EXTRACT:
        {
            returnCode = ExtractWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_SAVE:
        {
            returnCode = SaveWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        case JOB_STATUS_PRINT:
        {
            returnCode = PrintWebPage();
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            m_webPageMgr.ClearWebPageList();
            break;
        }
        case JOB_STATUS_COMPLETE:
        {
            returnCode = DeleteTask(task);
            if(!returnCode)
            {
                task->DeleteJob(job);
            }
            break;
        }
        default:
        {
            return COLLECTOR_JOB_ERROR_WRONG_STATUS;
        }
    }

    return returnCode;
}
Example #14
0
/* This function is launched in a separate thread and waits for 
 * a message from a completion port associated with a job.
 */
DWORD WINAPI JobNotify(PVOID) 
{
   TCHAR sz[2000];
   BOOL fDone = FALSE;

   while (!fDone) 
   {
      DWORD dwBytesXferred;
      ULONG_PTR CompKey;
      LPOVERLAPPED po;
      
	  /* Attempts to dequeue an I/O completion packet 
	   * from the specified I/O completion port. 
	   * If there is no completion packet queued, the function 
	   * waits for a pending I/O operation associated with the completion port to complete.
	   *
       * To dequeue multiple I/O completion packets at once, 
	   * use the GetQueuedCompletionStatusEx function
	   *  
	   * CompletionPort [in] 
       *   A handle to the completion port. To create a completion port, 
	   *   use the CreateIoCompletionPort function.
	   *
	   * lpNumberOfBytes [out] 
       *   A pointer to a variable that receives the number of bytes 
	   *   transferred during an I/O operation that has completed
       *   
	   * lpCompletionKey [out] 
       *   A pointer to a variable that receives the completion key value 
	   *   associated with the file handle whose I/O operation has completed. 
	   *   A completion key is a per-file key that is specified in a call to CreateIoCompletionPort.
       *
	   * lpOverlapped [out]  
       *   A pointer to a variable that receives the address of the 
	   *   OVERLAPPED structure that was specified when the completed I/O operation was started. 
	   * 
	   * dwMilliseconds [in] 
       *   The number of milliseconds that the caller is willing to wait 
	   *   for a completion packet to appear at the completion port. 
	   *   If a completion packet does not appear within the specified time, 
	   *   the function times out, returns FALSE, and sets *lpOverlapped to NULL.
	   *
       *   If dwMilliseconds is INFINITE, the function will never time out. 
	   *   If dwMilliseconds is zero and there is no I/O operation to dequeue, 
	   *   the function will time out immediately.
       */
      GetQueuedCompletionStatus(
		  g_hIOCP, 
          &dwBytesXferred, 
		  &CompKey, 
		  &po, 
		  INFINITE);

      /* The app is shutting down, exit this thread */
      fDone = (CompKey == COMPKEY_TERMINATE);

      HWND hwndLB = FindWindow(NULL, TEXT("Job Lab"));
      hwndLB = GetDlgItem(hwndLB, IDC_STATUS);

      if (CompKey == COMPKEY_JOBOBJECT) 
	  {
         _tcscpy_s(sz, _countof(sz), TEXT("--> Notification: "));
         PTSTR psz = sz + _tcslen(sz);
         switch (dwBytesXferred) 
		 {
			 /* We have reached an event when job time was reached */
             case JOB_OBJECT_MSG_END_OF_JOB_TIME:
                  StringCchPrintf(
					    psz, 
						_countof(sz) - _tcslen(sz), 
                        TEXT("Job time limit reached"));
             break;
			 /* The time allowed for process in the job is exceeded.
			  * So we get process name from the overlapped structure.
			  */
             case JOB_OBJECT_MSG_END_OF_PROCESS_TIME: 
			 {
                  TCHAR szProcessName[MAX_PATH];
                  
				  /* po is a process identifier. */
                  GetProcessName(
					  PtrToUlong(po), 
					  szProcessName, 
					  MAX_PATH);

                  StringCchPrintf(
					  psz, 
					  _countof(sz) - _tcslen(sz), 
                      TEXT("Job process %s (Id=%d) time limit reached"), 
                      szProcessName, 
					  po);
             }
             break;

             case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:
                  StringCchPrintf(
					  psz, 
					  _countof(sz) - _tcslen(sz), 
                      TEXT("Too many active processes in job"));
             break;

             case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
                  StringCchPrintf(
					  psz, 
					  _countof(sz) - _tcslen(sz), 
                      TEXT("Job contains no active processes"));
             break;

             case JOB_OBJECT_MSG_NEW_PROCESS: 
			 {
                  TCHAR szProcessName[MAX_PATH];
                  GetProcessName(
					  PtrToUlong(po), 
					  szProcessName, 
					  MAX_PATH);

                  StringCchPrintf(
					  psz, 
					  _countof(sz) - _tcslen(sz), 
                      TEXT("New process %s (Id=%d) in Job"), 
					  szProcessName, 
					  po);
             }
             break;

             case JOB_OBJECT_MSG_EXIT_PROCESS: 
			 {
                  TCHAR szProcessName[MAX_PATH];
                  GetProcessName(
					 PtrToUlong(po), 
					 szProcessName, 
					 MAX_PATH);

                  StringCchPrintf(
					  psz, 
					  _countof(sz) - _tcslen(sz), 
                      TEXT("Process %s (Id=%d) terminated"), 
					  szProcessName, 
					  po);
             }
             break;

             case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: 
			 {
                 TCHAR szProcessName[MAX_PATH];
                 GetProcessName(
					 PtrToUlong(po), 
					 szProcessName, 
					 MAX_PATH);

                 StringCchPrintf(
					 psz, 
					 _countof(sz) - _tcslen(sz), 
                     TEXT("Process %s (Id=%d) terminated abnormally"), 
                     szProcessName, 
					 po);
             }
             break;

             case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: 
		     {
                 TCHAR szProcessName[MAX_PATH];
                 GetProcessName(
					 PtrToUlong(po), 
					 szProcessName, 
					 MAX_PATH);

                 StringCchPrintf(
					 psz, 
					 _countof(sz) - _tcslen(sz), 
                     TEXT("Process (%s Id=%d) exceeded memory limit"), 
                     szProcessName, 
					 po);
             }
             break;

             case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: 
			 {
                 TCHAR szProcessName[MAX_PATH];
                 GetProcessName(
					 PtrToUlong(po), 
					 szProcessName, 
					 MAX_PATH);

                 StringCchPrintf(
					 psz, 
					 _countof(sz) - _tcslen(sz),
                     TEXT("Process %s (Id=%d) exceeded job memory limit"), 
                     szProcessName, 
					 po);
             }
             break;

             default:
                 StringCchPrintf(
					 psz, 
					 _countof(sz) - _tcslen(sz),
                     TEXT("Unknown notification: %d"), 
					 dwBytesXferred);
             break;
         }
         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
         /* Force a status update when a notification arrives */
         CompKey = 1; 
      }

      if (CompKey == COMPKEY_STATUS) 
	  {
         static int s_nStatusCount = 0;

         StringCchPrintf(
			 sz, 
			 _countof(sz), 
             TEXT("--> Status Update (%u)"), 
			 s_nStatusCount++);

         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         /* Show the basic accounting information */
         JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION jobai;

         g_job.QueryBasicAccountingInfo(&jobai);

         StringCchPrintf(
			 sz, 
			 _countof(sz), 
             TEXT("Total Time: User=%I64u, Kernel=%I64u        ")
             TEXT("Period Time: User=%I64u, Kernel=%I64u"), 
             jobai.BasicInfo.TotalUserTime.QuadPart, 
             jobai.BasicInfo.TotalKernelTime.QuadPart,
             jobai.BasicInfo.ThisPeriodTotalUserTime.QuadPart, 
             jobai.BasicInfo.ThisPeriodTotalKernelTime.QuadPart);

         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         StringCchPrintf(
			 sz, 
			 _countof(sz), 
             TEXT("Page Faults=%u, Total Processes=%u, ")
             TEXT("Active Processes=%u, Terminated Processes=%u"), 
             jobai.BasicInfo.TotalPageFaultCount, 
             jobai.BasicInfo.TotalProcesses, 
             jobai.BasicInfo.ActiveProcesses, 
             jobai.BasicInfo.TotalTerminatedProcesses);

         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         /* Show the I/O accounting information */
         StringCchPrintf(
			 sz, 
			 _countof(sz), 
             TEXT("Reads=%I64u (%I64u bytes), ")
             TEXT("Write=%I64u (%I64u bytes), Other=%I64u (%I64u bytes)"), 
             jobai.IoInfo.ReadOperationCount,  
			 jobai.IoInfo.ReadTransferCount, 
             jobai.IoInfo.WriteOperationCount, 
			 jobai.IoInfo.WriteTransferCount, 
             jobai.IoInfo.OtherOperationCount, 
			 jobai.IoInfo.OtherTransferCount);

         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         /* Show the peak per-process and job memory usage */
         JOBOBJECT_EXTENDED_LIMIT_INFORMATION joeli;
         g_job.QueryExtendedLimitInfo(&joeli);

         StringCchPrintf(
			 sz, 
			 _countof(sz), 
             TEXT("Peak memory used: Process=%I64u, Job=%I64u"), 
             (__int64)joeli.PeakProcessMemoryUsed, 
             (__int64)joeli.PeakJobMemoryUsed);
         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         /* Show the set of Process IDs */
         DWORD dwNumProcesses = 50;
         DWORD dwProcessIdList[50];

         g_job.QueryBasicProcessIdList(
			 dwNumProcesses, 
             dwProcessIdList, 
			 &dwNumProcesses);

         StringCchPrintf(
			 sz, 
			 _countof(sz), 
			 TEXT("PIDs: %s"), 
             (dwNumProcesses == 0) ? TEXT("(none)") : TEXT(""));

         ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));

         TCHAR szProcessName[MAX_PATH];

         for (DWORD x = 0; x < dwNumProcesses; x++) 
		 {
            GetProcessName(
				dwProcessIdList[x], 
                szProcessName, 
				_countof(szProcessName));

            StringCchPrintf(
				sz, 
				_countof(sz), 
				TEXT("   %d - %s"), 
                dwProcessIdList[x], 
				szProcessName);

            ListBox_SetCurSel(hwndLB, ListBox_AddString(hwndLB, sz));
         }
      }
   }

   return(0);
}
Example #15
0
int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE, PTSTR pszCmdLine, int) 
{
   /* Check if we are not already associated with a job.
    * If this is the case, there is no way to switch to
    * another job.
	*/
   BOOL bInJob = FALSE;
   IsProcessInJob(GetCurrentProcess(), NULL, &bInJob);
   if (bInJob) 
   {
      MessageBox(
		  NULL, 
		  TEXT("Process already in a job"), 
          TEXT(""), 
		  MB_ICONINFORMATION | MB_OK);

      return(-1);
   }

   /* Create the completion port that receives job notifications 
    * Creates an input/output (I/O) completion port 
	* and associates it with a specified file handle, 
	* or creates an I/O completion port that is not 
	* yet associated with a file handle, allowing association at a later time.
    * 
	*  Associating an instance of an opened file handle with an I/O completion 
	*  port allows a process to receive notification of the completion 
	*  of asynchronous I/O operations involving that file handle.
	*
    * FileHandle [in] 
    *   An open file handle or INVALID_HANDLE_VALUE.
    *   The handle must be to an object that supports overlapped I/O.
    *   If a handle is provided, it has to have been opened 
	*   for overlapped I/O completion. 
	*   For example, you must specify the FILE_FLAG_OVERLAPPED flag
	*   when using the CreateFile function to obtain the handle.
	*
    *   If INVALID_HANDLE_VALUE is specified, 
	*   the function creates an I/O completion port without associating it 
	*   with a file handle. In this case, the ExistingCompletionPort parameter 
	*   must be NULL and the CompletionKey parameter is ignored.
    * 
	* ExistingCompletionPort [in, optional] 
    *   A handle to an existing I/O completion port or NULL.
    *   If this parameter is NULL, the function creates a new I/O completion port and, 
	*   if the FileHandle parameter is valid, associates it with the new I/O completion port. 
	*   Otherwise no file handle association occurs. 
	*   The function returns the handle to the new I/O completion port if successful.
	*  
	*  
    */
   g_hIOCP = CreateIoCompletionPort(
	   INVALID_HANDLE_VALUE, 
	   NULL, 
	   0, 
	   0);

   /* Create a thread that waits on the completion port */
   g_hThreadIOCP = chBEGINTHREADEX(
	   NULL, 
	   0, 
	   JobNotify, 
	   NULL, 
	   0, 
	   NULL);

   /* Create the job object */
   g_job.Create(NULL, TEXT("JobLab"));
   g_job.SetEndOfJobInfo(JOB_OBJECT_POST_AT_END_OF_JOB);
   g_job.AssociateCompletionPort(g_hIOCP, COMPKEY_JOBOBJECT);

   DialogBox(hinstExe, MAKEINTRESOURCE(IDD_JOBLAB), NULL, Dlg_Proc);

   /* Post a special key that tells the completion port thread to terminate 
    * Posts an I/O completion packet to an I/O completion port.
	*
	* CompletionPort [in] 
    *   A handle to an I/O completion port to which 
	*   the I/O completion packet is to be posted.
    * 
	* dwNumberOfBytesTransferred [in] 
    *   The value to be returned through the lpNumberOfBytesTransferred 
	*   parameter of the GetQueuedCompletionStatus function.
    *
	* dwCompletionKey [in] 
    *   The value to be returned through the lpCompletionKey parameter 
	*   of the GetQueuedCompletionStatus function.
    * 
	* lpOverlapped [in, optional] 
    *   The value to be returned through the lpOverlapped parameter 
	*   of the GetQueuedCompletionStatus function.
    *
    */
   PostQueuedCompletionStatus(g_hIOCP, 0, COMPKEY_TERMINATE, NULL);

   /* Wait for the completion port thread to terminate */
   WaitForSingleObject(g_hThreadIOCP, INFINITE);
   
   // Clean up everything properly
   CloseHandle(g_hIOCP);
   CloseHandle(g_hThreadIOCP);

   // NOTE: The job is closed when the g_job's destructor is called.
   return(0);
}
Example #16
0
void Dlg_ApplyLimits(HWND hwnd) {
   const int nNanosecondsPerSecond = 1000000000;
   const int nMillisecondsPerSecond = 1000;
   const int nNanosecondsPerMillisecond = 
      nNanosecondsPerSecond / nMillisecondsPerSecond;
   BOOL f;
   __int64 q;
   SIZE_T s;
   DWORD d;

   // Set Basic and Extended Limits
   JOBOBJECT_EXTENDED_LIMIT_INFORMATION joeli = { 0 };
   joeli.BasicLimitInformation.LimitFlags = 0;
   
   q = GetDlgItemInt(hwnd, IDC_PERPROCESSUSERTIMELIMIT, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PROCESS_TIME;
      joeli.BasicLimitInformation.PerProcessUserTimeLimit.QuadPart = 
         q * nNanosecondsPerMillisecond / 100;
   }

   q = GetDlgItemInt(hwnd, IDC_PERJOBUSERTIMELIMIT, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_TIME;
      joeli.BasicLimitInformation.PerJobUserTimeLimit.QuadPart = 
         q * nNanosecondsPerMillisecond / 100;
   }

   s = GetDlgItemInt(hwnd, IDC_MINWORKINGSETSIZE, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_WORKINGSET;
      joeli.BasicLimitInformation.MinimumWorkingSetSize = s * 1024 * 1024;
      s = GetDlgItemInt(hwnd, IDC_MAXWORKINGSETSIZE, &f, FALSE);
      if (f) {
         joeli.BasicLimitInformation.MaximumWorkingSetSize = s * 1024 * 1024;
      } else {
         joeli.BasicLimitInformation.LimitFlags &=~JOB_OBJECT_LIMIT_WORKINGSET;
         chMB("Both minimum and maximum working set sizes must be set.\n"
            "The working set limits will NOT be in effect.");
      }
   }

   d = GetDlgItemInt(hwnd, IDC_ACTIVEPROCESSLIMIT, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= 
         JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
      joeli.BasicLimitInformation.ActiveProcessLimit = d;
   }

   s = GetDlgItemInt(hwnd, IDC_AFFINITYMASK, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_AFFINITY;
      joeli.BasicLimitInformation.Affinity = s;
   }

   joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
   switch (ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_PRIORITYCLASS))) {
      case 0: 
         joeli.BasicLimitInformation.LimitFlags &= 
            ~JOB_OBJECT_LIMIT_PRIORITY_CLASS;
         break;

      case 1: 
         joeli.BasicLimitInformation.PriorityClass = 
            IDLE_PRIORITY_CLASS;
         break;

      case 2: 
         joeli.BasicLimitInformation.PriorityClass = 
            BELOW_NORMAL_PRIORITY_CLASS; 
         break;

      case 3: 
         joeli.BasicLimitInformation.PriorityClass = 
            NORMAL_PRIORITY_CLASS;       
         break;

      case 4: 
         joeli.BasicLimitInformation.PriorityClass = 
            ABOVE_NORMAL_PRIORITY_CLASS; 
         break;

      case 5: 
         joeli.BasicLimitInformation.PriorityClass = 
            HIGH_PRIORITY_CLASS;         
         break;

      case 6: 
         joeli.BasicLimitInformation.PriorityClass = 
            REALTIME_PRIORITY_CLASS;     
         break;
   }

   int nSchedulingClass = 
      ComboBox_GetCurSel(GetDlgItem(hwnd, IDC_SCHEDULINGCLASS));
   if (nSchedulingClass > 0) {
      joeli.BasicLimitInformation.LimitFlags |= 
         JOB_OBJECT_LIMIT_SCHEDULING_CLASS;
      joeli.BasicLimitInformation.SchedulingClass = nSchedulingClass - 1;
   }

   s = GetDlgItemInt(hwnd, IDC_MAXCOMMITPERJOB, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_JOB_MEMORY;
      joeli.JobMemoryLimit = s * 1024 * 1024;
   }

   s = GetDlgItemInt(hwnd, IDC_MAXCOMMITPERPROCESS, &f, FALSE);
   if (f) {
      joeli.BasicLimitInformation.LimitFlags |= 
         JOB_OBJECT_LIMIT_PROCESS_MEMORY;
      joeli.ProcessMemoryLimit = s * 1024 * 1024;
   }

   if (IsDlgButtonChecked(hwnd, IDC_CHILDPROCESSESCANBREAKAWAYFROMJOB))
      joeli.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_BREAKAWAY_OK;

   if (IsDlgButtonChecked(hwnd, IDC_CHILDPROCESSESDOBREAKAWAYFROMJOB))
      joeli.BasicLimitInformation.LimitFlags |= 
      JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;

   if (IsDlgButtonChecked(hwnd, IDC_TERMINATEPROCESSONEXCEPTIONS))
      joeli.BasicLimitInformation.LimitFlags |= 
      JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;

   f = g_job.SetExtendedLimitInfo(&joeli, 
      ((joeli.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_JOB_TIME) 
         != 0) ? FALSE : 
         IsDlgButtonChecked(hwnd, IDC_PRESERVEJOBTIMEWHENAPPLYINGLIMITS));
   chASSERT(f);

   // Set UI Restrictions
   DWORD jobuir =  JOB_OBJECT_UILIMIT_NONE;  // A fancy zero (0)
   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTACCESSTOOUTSIDEUSEROBJECTS))
      jobuir |=  JOB_OBJECT_UILIMIT_HANDLES;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTREADINGCLIPBOARD))
      jobuir |=  JOB_OBJECT_UILIMIT_READCLIPBOARD;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTWRITINGCLIPBOARD))
      jobuir |=  JOB_OBJECT_UILIMIT_WRITECLIPBOARD;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTEXITWINDOW))
      jobuir |=  JOB_OBJECT_UILIMIT_EXITWINDOWS;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTCHANGINGSYSTEMPARAMETERS))
      jobuir |=  JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS;
   
   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTDESKTOPS))
      jobuir |= JOB_OBJECT_UILIMIT_DESKTOP;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTDISPLAYSETTINGS))
      jobuir |= JOB_OBJECT_UILIMIT_DISPLAYSETTINGS;

   if (IsDlgButtonChecked(hwnd, IDC_RESTRICTGLOBALATOMS))
      jobuir |=  JOB_OBJECT_UILIMIT_GLOBALATOMS;
   
   chVERIFY(g_job.SetBasicUIRestrictions(jobuir));
}