//----------------------------------------------------------------------------- // Creates the canary thread and signaling events. //----------------------------------------------------------------------------- void HelperCanary::Init() { // You can only run the init code once. The debugger attempts to lazy-init // the canary at several points but if the canary is already inited then // we just eagerly return. See issue 841005 for more details. if(m_initialized) { return; } else { m_initialized = true; } m_hPingEvent = WszCreateEvent(NULL, (BOOL) kAutoResetEvent, FALSE, NULL); if (m_hPingEvent == NULL) { STRESS_LOG1(LF_CORDB, LL_ALWAYS, "Canary failed to create ping event. gle=%d\n", GetLastError()); // in the past if we failed to start the thread we just assumed it was unsafe // so I am preserving that behavior. However I am going to assert that this // doesn't really happen _ASSERTE(!"Canary failed to create ping event"); return; } m_hWaitEvent = WszCreateEvent(NULL, (BOOL) kManualResetEvent, FALSE, NULL); if (m_hWaitEvent == NULL) { STRESS_LOG1(LF_CORDB, LL_ALWAYS, "Canary failed to create wait event. gle=%d\n", GetLastError()); // in the past if we failed to start the thread we just assumed it was unsafe // so I am preserving that behavior. However I am going to assert that this // doesn't really happen _ASSERTE(!"Canary failed to create wait event"); return; } // Spin up the canary. This will call dllmain, but that's ok because it just // degenerates to our timeout case. const DWORD flags = CREATE_SUSPENDED; m_hCanaryThread = CreateThread(NULL, 0, HelperCanary::ThreadProc, this, flags, &m_CanaryThreadId); // in the past if we failed to start the thread we just assumed it was unsafe // so I am preserving that behavior. However I am going to assert that this // doesn't really happen if(m_hCanaryThread == NULL) { _ASSERTE(!"CreateThread() failed to create Canary thread"); return; } // Capture the Canary thread's TID so that the RS can mark it as a can't-stop region. // This is essential so that the RS doesn't view it as some external thread to be suspended when we hit // debug events. _ASSERTE(g_pRCThread != NULL); g_pRCThread->GetDCB()->m_CanaryThreadId = m_CanaryThreadId; ResumeThread(m_hCanaryThread); }
HRESULT DebuggerRCThread::CreateSetupSyncEvent(void) { WCHAR tmpName[256]; HRESULT hr = S_OK; // Attempt to create the Setup Sync event. swprintf(tmpName, CorDBIPCSetupSyncEventName, GetCurrentProcessId()); LOG((LF_CORDB, LL_INFO10000, "DRCT::I: creating setup sync event with name [%S]\n", tmpName)); SECURITY_ATTRIBUTES *pSA = NULL; hr = g_pIPCManagerInterface->GetSecurityAttributes(GetCurrentProcessId(), &pSA); if (FAILED(hr)) goto exit; m_SetupSyncEvent = WszCreateEvent(pSA, TRUE, FALSE, tmpName); // Do not fail because we cannot create the setup sync event. exit: g_pIPCManagerInterface->DestroySecurityAttributes(pSA); return hr; }
HRESULT FusionSink::AssemblyCreateEvent() { HRESULT hr = S_OK; if(m_hEvent == NULL) { // Initialize the event to require manual reset // and to initially signaled. m_hEvent = WszCreateEvent(NULL, TRUE, TRUE, NULL); if(m_hEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); } } return hr; }
BOOL LaunchJITDebugger() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_DEBUG_ONLY; BOOL fSuccess = FALSE; #ifndef FEATURE_PAL EX_TRY { SString debugger; GetDebuggerSettingInfo(debugger, NULL); SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // We can leave this event as it is since it is inherited by a child process. // We will block one scheduler, but the process is asking a user if they want to attach debugger. HandleHolder eventHandle = WszCreateEvent(&sa, TRUE, FALSE, NULL); if (eventHandle == NULL) ThrowOutOfMemory(); SString cmdLine; cmdLine.Printf(debugger, GetCurrentProcessId(), eventHandle.GetValue()); STARTUPINFO StartupInfo; memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = sizeof(StartupInfo); StartupInfo.lpDesktop = W("Winsta0\\Default"); PROCESS_INFORMATION ProcessInformation; if (WszCreateProcess(NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInformation)) { WaitForSingleObject(eventHandle.GetValue(), INFINITE); } fSuccess = TRUE; } EX_CATCH { } EX_END_CATCH(SwallowAllExceptions); #endif // !FEATURE_PAL return fSuccess; }
void CreateProgressBar(LONG lRange) { DWORD dwThreadID; g_ulCount = 0; if((g_ulRange = (ULONG)lRange)==0) return; g_hThreadReady = WszCreateEvent(NULL,FALSE,FALSE,NULL); if (g_hThreadReady != NULL) { // Thread is never aborted, it always exits by itself HANDLE hThread = CreateThread(NULL,0,ProgressMainLoop,NULL,0,&dwThreadID); if (hThread != NULL) { CloseHandle(hThread); WaitForSingleObject(g_hThreadReady,INFINITE); } CloseHandle(g_hThreadReady); } }
//----------------------------------------------------------------------------- // Receieves the call. This should be in a different process than the source //----------------------------------------------------------------------------- HRESULT IPCFuncCallHandler::InitFCHandler(HANDLER_CALLBACK pfnCallback) { m_pfnCallback = pfnCallback; HRESULT hr = NOERROR; DWORD dwThreadId; DWORD dwErr = 0; SetLastError(0); SECURITY_ATTRIBUTES *pSA = NULL; // Grab the SA DWORD dwPid = GetCurrentProcessId(); hr = IPCShared::CreateWinNTDescriptor(dwPid, &pSA); if (FAILED(hr)) goto errExit;; // Create the StartEnum Event m_hStartEnum = WszCreateEvent(pSA, FALSE, FALSE, FixupName(StartEnumEventName)); if (m_hStartEnum == NULL) { dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the EndEnumEvent m_hDoneEnum = WszCreateEvent(pSA, FALSE, FALSE, FixupName(DoneEnumEventName)); if (m_hDoneEnum == NULL) { dwErr = GetLastError(); hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the ShutdownThread Event m_hShutdownThread = WszCreateEvent(pSA, TRUE, /* Manual Reset */ FALSE, /* Initial state not signalled */ NULL); dwErr = GetLastError(); if (m_hShutdownThread == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create the AuxThreadShutdown Event m_hAuxThreadShutdown = WszCreateEvent(pSA, TRUE, /* Manual Reset */ FALSE, NULL); dwErr = GetLastError(); if (m_hAuxThreadShutdown == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // The thread that we are about to create should always // find the code in memory. So we take a ref on the DLL. // and do a free library at the end of the thread's start function m_hCallbackModule = WszLoadLibrary (L"CorPerfmonExt.dll"); dwErr = GetLastError(); if (m_hCallbackModule == NULL) { hr = HRESULT_FROM_WIN32(dwErr); goto errExit; } // Create thread m_hAuxThread = CreateThread( NULL, 0, HandlerAuxThreadProc, this, 0, &dwThreadId); dwErr = GetLastError(); if (m_hAuxThread == NULL) { hr = HRESULT_FROM_WIN32(dwErr); // In case of an error free this library here otherwise // the thread's exit would take care of it. if (m_hCallbackModule) FreeLibrary (m_hCallbackModule); goto errExit; } errExit: if (!SUCCEEDED(hr)) { TerminateFCHandler(); } return hr; }
// // Init sets up all the objects that the RC thread will need to run. // HRESULT DebuggerRCThread::Init(void) { HRESULT hr = S_OK; HANDLE rightSideEventAvailable = NULL; HANDLE rightSideEventRead = NULL; HANDLE leftSideUnmanagedWaitEvent = NULL; HANDLE syncThreadIsLockFree = NULL; WCHAR tmpName[256]; NAME_EVENT_BUFFER; SECURITY_ATTRIBUTES *pSA = NULL; if (m_debugger == NULL) return E_INVALIDARG; // Init should only be called once. if (g_pRCThread != NULL) return E_FAIL; g_pRCThread = this; m_rgDCB = new DebuggerIPCControlBlock *[IPC_TARGET_COUNT]; if (NULL == m_rgDCB) { return E_OUTOFMEMORY; } memset( m_rgDCB, 0, sizeof(DebuggerIPCControlBlock *)*IPC_TARGET_COUNT); // Create 2 events for managing favors: unnamed, auto-reset, default=not-signaled m_FavorAvailableEvent = WszCreateEvent(NULL, FALSE, FALSE, NULL); if (m_FavorAvailableEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } m_FavorReadEvent = WszCreateEvent(NULL, FALSE, FALSE, NULL); if (m_FavorReadEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } // Create the thread control event. m_threadControlEvent = WszCreateEvent(NULL, FALSE, FALSE, NAME_EVENT(L"ThreadControlEvent")); if (m_threadControlEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } // Create the helper thread can go event. Manual reset, and // initially signaled. m_helperThreadCanGoEvent = WszCreateEvent(NULL, TRUE, TRUE, NAME_EVENT(L"HelperThreadCanGoEvent")); if (m_helperThreadCanGoEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } // We need to setup the shared memory and control block. // Get shared memory block from the IPCManager. if (g_pIPCManagerInterface == NULL) { LOG((LF_CORDB, LL_INFO10000, "DRCT::I: g_pIPCManagerInterface == NULL, can't create IPC Block\n")); hr = E_FAIL; goto exit; } hr = g_pIPCManagerInterface->GetSecurityAttributes(GetCurrentProcessId(), &pSA); if (FAILED(hr)) goto exit; // Create the events that the thread will need to receive events // from the out of process piece on the right side. // We will not fail out if CreateEvent fails for RSEA or RSER. Because // the worst case is that debugger cannot attach to debuggee. // rightSideEventAvailable = WszCreateEvent(pSA, FALSE, FALSE, NAME_EVENT(L"RightSideEventAvailable")); rightSideEventRead = WszCreateEvent(pSA, FALSE, FALSE, NAME_EVENT(L"RightSideEventRead")); leftSideUnmanagedWaitEvent = WszCreateEvent(NULL, TRUE, FALSE, NAME_EVENT(L"LeftSideUnmanagedWaitEvent")); if (leftSideUnmanagedWaitEvent == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } syncThreadIsLockFree = WszCreateEvent(NULL, TRUE, FALSE, NAME_EVENT(L"SyncThreadIsLockFree")); if (syncThreadIsLockFree == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } m_rgDCB[IPC_TARGET_OUTOFPROC] = g_pIPCManagerInterface->GetDebugBlock(); // Don't fail out because the SHM failed to create #if _DEBUG if (m_rgDCB[IPC_TARGET_OUTOFPROC] == NULL) { LOG((LF_CORDB, LL_INFO10000, "DRCT::I: Failed to get Debug IPC block from IPCManager.\n")); } #endif // _DEBUG // Copy RSEA and RSER into the control block only if SHM is created without error. if (m_rgDCB[IPC_TARGET_OUTOFPROC]) { hr = m_rgDCB[IPC_TARGET_OUTOFPROC]->Init(rightSideEventAvailable, rightSideEventRead, NULL, NULL, leftSideUnmanagedWaitEvent, syncThreadIsLockFree); if (FAILED(hr)) goto exit; // We have to ensure that most of the runtime offsets for the out-of-proc DCB are initialized right away. This is // needed to support certian races during an interop attach. Since we can't know whether an interop attach will ever // happen or not, we are forced to do this now. Note: this is really too early, as some data structures haven't been // initialized yet! hr = EnsureRuntimeOffsetsInit(IPC_TARGET_OUTOFPROC); if (FAILED(hr)) goto exit; // Note: we have to mark that we need the runtime offsets re-initialized for the out-of-proc DCB. This is because // things like the patch table aren't initialized yet. Calling NeedRuntimeOffsetsReInit() ensures that this happens // before we really need the patch table. NeedRuntimeOffsetsReInit(IPC_TARGET_OUTOFPROC); m_rgDCB[IPC_TARGET_OUTOFPROC]->m_helperThreadStartAddr = (void *) DebuggerRCThread::ThreadProcStatic; m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideProtocolCurrent = CorDB_LeftSideProtocolCurrent; m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideProtocolMinSupported = CorDB_LeftSideProtocolMinSupported; LOG((LF_CORDB, LL_INFO10, "DRCT::I: version info: %d.%d.%d current protocol=%d, min protocol=%d\n", m_rgDCB[IPC_TARGET_OUTOFPROC]->m_verMajor, m_rgDCB[IPC_TARGET_OUTOFPROC]->m_verMinor, m_rgDCB[IPC_TARGET_OUTOFPROC]->m_checkedBuild, m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideProtocolCurrent, m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideProtocolMinSupported)); } // Next we'll create the setup sync event for the right side - this // solves a race condition of "who gets to the setup code first?" // Since there's no guarantee that the thread executing managed // code will be executed after us, we've got to do this for // the inproc portion of the code, as well. hr = CreateSetupSyncEvent(); if (FAILED(hr)) goto exit; if (GetLastError() == ERROR_ALREADY_EXISTS) { // the event already exists. LOG((LF_CORDB, LL_INFO10000, "DRCT::I: setup sync event already exists.\n")); // Need to do some delayed initialization of the debugger services. DebuggerController::Initialize(); // Wait for the Setup Sync event before continuing. DWORD ret = WaitForSingleObject(m_SetupSyncEvent, INFINITE); if (ret != WAIT_OBJECT_0) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } // We no longer need this event now. CloseHandle(m_SetupSyncEvent); m_SetupSyncEvent = NULL; // Open LSEA and LSER (which would have been // created by Right side) swprintf(tmpName, CorDBIPCLSEventAvailName, GetCurrentProcessId()); if (m_rgDCB[IPC_TARGET_OUTOFPROC]) { m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideEventAvailable = WszOpenEvent(EVENT_ALL_ACCESS, true, tmpName ); if (m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideEventAvailable == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } } swprintf(tmpName, CorDBIPCLSEventReadName, GetCurrentProcessId()); if (m_rgDCB[IPC_TARGET_OUTOFPROC]) { m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideEventRead = WszOpenEvent(EVENT_ALL_ACCESS, true, tmpName ); if (m_rgDCB[IPC_TARGET_OUTOFPROC]->m_leftSideEventRead == NULL) { hr = HRESULT_FROM_WIN32(GetLastError()); goto exit; } } LOG((LF_CORDB, LL_INFO10000,"DRCT::I: calling PAL_InitializeDebug.\n")); // Tell the PAL that we're trying to debug PAL_InitializeDebug(); // At this point, the control block is complete and all four // events are available and valid for this process. // Since the sync event was created by the Right Side, // we'll need to mark the debugger as "attached." g_pEEInterface->MarkDebuggerAttached(); m_debugger->m_debuggerAttached = TRUE; } else { LOG((LF_CORDB, LL_INFO10000, "DRCT::I: setup sync event was created.\n")); // At this point, only RSEA and RSER are in the control // block. LSEA and LSER will remain invalid until the first // receipt of an event from the Right Side. // Set the Setup Sync event to let the Right Side know that // we've finished setting up the control block. SetEvent(m_SetupSyncEvent); } // Now do this all again for the inproc stuff m_rgDCB[IPC_TARGET_INPROC] = GetInprocControlBlock(); if (m_rgDCB[IPC_TARGET_INPROC] == NULL) { hr = E_OUTOFMEMORY; goto exit; } m_rgDCB[IPC_TARGET_INPROC]->Init(NULL, NULL, NULL, NULL, NULL, NULL); exit: g_pIPCManagerInterface->DestroySecurityAttributes(pSA); return hr; }