// Attach the debugger to this process. HRESULT DbgTransportPipeline::DebugActiveProcess(MachineInfo machineInfo, DWORD processId) { // INativeEventPipeline has a 1:1 relationship with CordbProcess. _ASSERTE(!IsTransportRunning()); HRESULT hr = E_FAIL; m_pProxy = g_pDbgTransportTarget; // Establish a connection to the actual runtime to be debugged. hr = m_pProxy->GetTransportForProcess(processId, &m_pTransport, &m_hProcess); if (SUCCEEDED(hr)) { // TODO: Pass this timeout as a parameter all the way from debugger // Wait for the connection to become useable (or time out). if (!m_pTransport->WaitForSessionToOpen(10000)) { hr = CORDBG_E_TIMEOUT; } else { if (!m_pTransport->UseAsDebugger(&m_ticket)) { hr = CORDBG_E_DEBUGGER_ALREADY_ATTACHED; } } } if (SUCCEEDED(hr)) { m_dwProcessId = processId; m_fRunning = TRUE; } else { Dispose(); } return hr; }
// Create an process under the debugger. HRESULT DbgTransportPipeline::CreateProcessUnderDebugger( MachineInfo machineInfo, LPCWSTR lpApplicationName, LPCWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { // INativeEventPipeline has a 1:1 relationship with CordbProcess. _ASSERTE(!IsTransportRunning()); // We don't support interop-debugging on the Mac. _ASSERTE(!(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))); // When we're using a transport we can't deal with creating a suspended process (we need the process to // startup in order that it can start up a transport thread and reply to our messages). _ASSERTE(!(dwCreationFlags & CREATE_SUSPENDED)); // Connect to the debugger proxy on the remote machine and ask it to create a process for us. HRESULT hr = E_FAIL; m_pProxy = g_pDbgTransportTarget; hr = m_pProxy->CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); if (SUCCEEDED(hr)) { // Establish a connection to the actual runtime to be debugged. hr = m_pProxy->GetTransportForProcess(lpProcessInformation->dwProcessId, &m_pTransport, &m_hProcess); if (SUCCEEDED(hr)) { // Wait for the connection to become useable (or time out). if (!m_pTransport->WaitForSessionToOpen(10000)) { hr = CORDBG_E_TIMEOUT; } else { if (!m_pTransport->UseAsDebugger(&m_ticket)) { hr = CORDBG_E_DEBUGGER_ALREADY_ATTACHED; } } } } if (SUCCEEDED(hr)) { _ASSERTE((m_hProcess != NULL) && (m_hProcess != INVALID_HANDLE_VALUE)); m_dwProcessId = lpProcessInformation->dwProcessId; // For Mac remote debugging, we don't actually have a process handle to hand back to the debugger. // Instead, we return a handle to an event as the "process handle". The Win32 event thread also waits // on this event handle, and the event will be signaled when the proxy notifies us that the process // on the remote machine is terminated. However, normally the debugger calls CloseHandle() immediately // on the "process handle" after CreateProcess() returns. Doing so causes the Win32 event thread to // continue waiting on a closed event handle, and so it will never wake up. // (In fact, in Whidbey, we also duplicate the process handle in code:CordbProcess::Init.) if (!DuplicateHandle(GetCurrentProcess(), m_hProcess, GetCurrentProcess(), &(lpProcessInformation->hProcess), 0, // ignored since we are going to pass DUPLICATE_SAME_ACCESS FALSE, DUPLICATE_SAME_ACCESS)) { hr = HRESULT_FROM_GetLastError(); } } if (SUCCEEDED(hr)) { m_fRunning = TRUE; } else { Dispose(); } return hr; }