Exemple #1
0
//-----------------------------------------------------------------------------
// 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);
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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);
    }
}
Exemple #6
0
//-----------------------------------------------------------------------------
// 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;
 
}
Exemple #7
0
//
// 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;
}