You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
6.8 KiB

/*
* Copyright 2002-2019 Intel Corporation.
*
* This software is provided to you as Sample Source Code as defined in the accompanying
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
* section 1.L.
*
* This software and the related documents are provided as is, with no express or implied
* warranties, other than those that are expressly stated in the License.
*/
// MT Application that creates new processes, from multiple threads simultaneously
#include <Windows.h>
#include <iostream>
#include <string>
using std::string;
using std::endl;
using std::cout;
// The number 53 stresses the system up to the point of crashing due to resource exhaustion.
const LONG numthreads = 53;
LONG volatile numThreadsArrived = 0;
HANDLE threadReachedSynchPointSemHandle[numthreads];
CRITICAL_SECTION critSec;
void MutexWriteToStdout (char *msg)
{
EnterCriticalSection (&critSec);
printf (msg);
fflush (stdout);
LeaveCriticalSection (&critSec);
}
void MutexWriteToStdoutWithValue (char *msg, DWORD value)
{
EnterCriticalSection (&critSec);
printf (msg, value);
fflush (stdout);
LeaveCriticalSection (&critSec);
}
//Wait for a process completion
//Verify it returned the expected exit code
bool WaitAndVerify(HANDLE process)
{
if(WaitForSingleObject( process, INFINITE ) == WAIT_FAILED)
{
MutexWriteToStdout ("WaitForSingleObject failed\n");
return FALSE;
}
DWORD processExitCode;
if(GetExitCodeProcess (process, &processExitCode) == FALSE)
{
MutexWriteToStdout ("GetExitCodeProcess Failed\n");
return FALSE;
}
if(processExitCode != 0)
{
MutexWriteToStdoutWithValue ("Got unexpected exit code %x\n", processExitCode);
return FALSE;
}
return TRUE;
}
// Cause all threads to wait here until all the threads arrive here
void AllThreadSynchPoint (LONG threadNum)
{
LONG myNumThreadsArrived, i;
myNumThreadsArrived = InterlockedIncrement (&numThreadsArrived);
if (myNumThreadsArrived == numthreads)
{ // all threads have arrived
// wake the others
numThreadsArrived = 0; // reset for next thread synch point
for (i = 0; i < numthreads; i++)
{
if (i != threadNum)
{
ReleaseSemaphore (threadReachedSynchPointSemHandle[i], 1, NULL);
}
}
}
else
{ // thread waits here till all other threads arrive
WaitForSingleObject (threadReachedSynchPointSemHandle[threadNum], INFINITE);
}
}
DWORD WINAPI CreateTestProcesses(LPVOID threadNumPtr)
{
char cmd[] = "win_child_process.exe \"param1 param2\" param3 5000";
STARTUPINFO si;
PROCESS_INFORMATION pi;
LONG threadNum = (LONG)threadNumPtr;
BOOL ok;
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
memset(&pi, 0, sizeof(pi));
AllThreadSynchPoint(threadNum); // best attempt to get the threads to call CreateProcess
// simultaneously
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
{
DWORD lastError = GetLastError();
MutexWriteToStdoutWithValue ( "Couldn't create child process, code %x\n", lastError);
ok = FALSE;
}
else
{
CloseHandle (pi.hThread);
ok = WaitAndVerify(pi.hProcess);
CloseHandle (pi.hProcess);
}
AllThreadSynchPoint(threadNum);
if (ok)
{
MutexWriteToStdout ("First Process was created successfully!\n");
}
else
{
MutexWriteToStdoutWithValue ( "First Process was not created successfully in thread %d\n", threadNum);
}
//Create suspended
AllThreadSynchPoint(threadNum);
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
memset(&pi, 0, sizeof(pi));
if (!CreateProcess(NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
DWORD lastError = GetLastError();
MutexWriteToStdoutWithValue ( "Couldn't create child process suspended, code %x \n", lastError);
ok = FALSE;
}
else
{
ResumeThread( pi.hThread );
CloseHandle (pi.hThread);
ok = WaitAndVerify(pi.hProcess);
CloseHandle (pi.hProcess);
}
AllThreadSynchPoint(threadNum);
if (ok)
{
MutexWriteToStdout ("Second Process was created successfully!\n");
}
else
{
MutexWriteToStdoutWithValue ( "Second Process was not created successfully in thread %d\n", threadNum);
}
//Create process as user
AllThreadSynchPoint(threadNum);
HANDLE tokenHandle;
BOOL res = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tokenHandle);
if (!res)
{
MutexWriteToStdout ( "Couldn't open process token\n");
tokenHandle = NULL;
}
AllThreadSynchPoint(threadNum);
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
memset(&pi, 0, sizeof(pi));
if (!CreateProcessAsUser(tokenHandle, NULL, cmd, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
DWORD lastError = GetLastError();
CloseHandle (tokenHandle);
MutexWriteToStdoutWithValue ( "Couldn't create child process as user, code %x \n", lastError);
ok = FALSE;
}
else
{
CloseHandle (tokenHandle);
ResumeThread( pi.hThread );
CloseHandle (pi.hThread);
ok = WaitAndVerify(pi.hProcess);
CloseHandle (pi.hProcess);
}
AllThreadSynchPoint(threadNum);
if (ok)
{
MutexWriteToStdout ("Third Process was created successfully!\n");
}
else
{
MutexWriteToStdoutWithValue ( "Third Process was not created successfully in thread %d\n", threadNum);
}
return 0;
}
int main(int argc, char * argv[])
{
LONG i;
HANDLE threadHandles[numthreads];
if (numthreads > MAXIMUM_WAIT_OBJECTS)
{
cout << "exceeded limit of waitable objects\n";
return 2;
}
InitializeCriticalSection (&critSec);
for (i = 0; i < numthreads; i++)
{
threadReachedSynchPointSemHandle[i] = CreateSemaphore (NULL, 0, 1, NULL);
if (threadReachedSynchPointSemHandle[i] == NULL)
{
cout << "failed to create threadReachedSynchPointSemHandle\n";
return -1;
}
}
for (i = 0; i < numthreads; i++)
{
threadHandles[i] =
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateTestProcesses, (LPVOID)i, 0, NULL);
if (threadHandles[i] == NULL)
{
cout << "failed to create thread\n";
return -2;
}
}
// Wait until all threads terminated
WaitForMultipleObjects((DWORD)numthreads, threadHandles, TRUE, INFINITE);
DeleteCriticalSection (&critSec);
Sleep(1000);
return 0;
}