int VBoxDbgBase::dbgcCreate(PDBGCBACK pBack, unsigned fFlags) { PUVM pUVM = m_pUVM; if ( pUVM && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING) return DBGCCreate(pUVM, pBack, fFlags); return VERR_INVALID_HANDLE; }
int VBoxDbgBase::stamEnum(const QString &rPat, PFNSTAMR3ENUM pfnEnum, void *pvUser) { QByteArray Utf8Array = rPat.toUtf8(); const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL; PUVM pUVM = m_pUVM; if ( pUVM && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING) return STAMR3Enum(pUVM, pszPat, pfnEnum, pvUser); return VERR_INVALID_HANDLE; }
int VBoxDbgBase::stamReset(const QString &rPat) { QByteArray Utf8Array = rPat.toUtf8(); const char *pszPat = !rPat.isEmpty() ? Utf8Array.constData() : NULL; PUVM pUVM = m_pUVM; if ( pUVM && VMR3GetStateU(pUVM) < VMSTATE_DESTROYING) return STAMR3Reset(pUVM, pszPat); return VERR_INVALID_HANDLE; }
Console::teleporterSrcThreadWrapper(RTTHREAD hThread, void *pvUser) { TeleporterStateSrc *pState = (TeleporterStateSrc *)pvUser; /* * Console::teleporterSrc does the work, we just grab onto the VM handle * and do the cleanups afterwards. */ SafeVMPtr ptrVM(pState->mptrConsole); HRESULT hrc = ptrVM.rc(); if (SUCCEEDED(hrc)) hrc = pState->mptrConsole->teleporterSrc(pState); /* Close the connection ASAP on so that the other side can complete. */ if (pState->mhSocket != NIL_RTSOCKET) { RTTcpClientClose(pState->mhSocket); pState->mhSocket = NIL_RTSOCKET; } /* Aaarg! setMachineState trashes error info on Windows, so we have to complete things here on failure instead of right before cleanup. */ if (FAILED(hrc)) pState->mptrProgress->notifyComplete(hrc); /* We can no longer be canceled (success), or it doesn't matter any longer (failure). */ pState->mptrProgress->setCancelCallback(NULL, NULL); /* * Write lock the console before resetting mptrCancelableProgress and * fixing the state. */ AutoWriteLock autoLock(pState->mptrConsole COMMA_LOCKVAL_SRC_POS); pState->mptrConsole->mptrCancelableProgress.setNull(); VMSTATE const enmVMState = VMR3GetStateU(pState->mpUVM); MachineState_T const enmMachineState = pState->mptrConsole->mMachineState; if (SUCCEEDED(hrc)) { /* * Automatically shut down the VM on success. * * Note! We have to release the VM caller object or we'll deadlock in * powerDown. */ AssertLogRelMsg(enmVMState == VMSTATE_SUSPENDED, ("%s\n", VMR3GetStateName(enmVMState))); AssertLogRelMsg(enmMachineState == MachineState_TeleportingPausedVM, ("%s\n", Global::stringifyMachineState(enmMachineState))); ptrVM.release(); pState->mptrConsole->mVMIsAlreadyPoweringOff = true; /* (Make sure we stick in the TeleportingPausedVM state.) */ hrc = pState->mptrConsole->powerDown(); pState->mptrConsole->mVMIsAlreadyPoweringOff = false; pState->mptrProgress->notifyComplete(hrc); } else { /* * Work the state machinery on failure. * * If the state is no longer 'Teleporting*', some other operation has * canceled us and there is nothing we need to do here. In all other * cases, we've failed one way or another. */ if ( enmMachineState == MachineState_Teleporting || enmMachineState == MachineState_TeleportingPausedVM ) { if (pState->mfUnlockedMedia) { ErrorInfoKeeper Oak; HRESULT hrc2 = pState->mptrConsole->mControl->LockMedia(); if (FAILED(hrc2)) { uint64_t StartMS = RTTimeMilliTS(); do { RTThreadSleep(2); hrc2 = pState->mptrConsole->mControl->LockMedia(); } while ( FAILED(hrc2) && RTTimeMilliTS() - StartMS < 2000); } if (SUCCEEDED(hrc2)) pState->mfUnlockedMedia = true; else LogRel(("FATAL ERROR: Failed to re-take the media locks. hrc2=%Rhrc\n", hrc2)); } switch (enmVMState) { case VMSTATE_RUNNING: case VMSTATE_RUNNING_LS: case VMSTATE_DEBUGGING: case VMSTATE_DEBUGGING_LS: case VMSTATE_POWERING_OFF: case VMSTATE_POWERING_OFF_LS: case VMSTATE_RESETTING: case VMSTATE_RESETTING_LS: Assert(!pState->mfSuspendedByUs); Assert(!pState->mfUnlockedMedia); pState->mptrConsole->setMachineState(MachineState_Running); break; case VMSTATE_GURU_MEDITATION: case VMSTATE_GURU_MEDITATION_LS: pState->mptrConsole->setMachineState(MachineState_Stuck); break; case VMSTATE_FATAL_ERROR: case VMSTATE_FATAL_ERROR_LS: pState->mptrConsole->setMachineState(MachineState_Paused); break; default: AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState))); case VMSTATE_SUSPENDED: case VMSTATE_SUSPENDED_LS: case VMSTATE_SUSPENDING: case VMSTATE_SUSPENDING_LS: case VMSTATE_SUSPENDING_EXT_LS: if (!pState->mfUnlockedMedia) { pState->mptrConsole->setMachineState(MachineState_Paused); if (pState->mfSuspendedByUs) { autoLock.release(); int rc = VMR3Resume(VMR3GetVM(pState->mpUVM)); AssertLogRelMsgRC(rc, ("VMR3Resume -> %Rrc\n", rc)); autoLock.acquire(); } } else { /* Faking a guru meditation is the best I can think of doing here... */ pState->mptrConsole->setMachineState(MachineState_Stuck); } break; } } } autoLock.release(); /* * Cleanup. */ Assert(pState->mhSocket == NIL_RTSOCKET); delete pState; return VINF_SUCCESS; /* ignored */ }
/** * Creates a TCP server that listens for the source machine and passes control * over to Console::teleporterTrgServeConnection(). * * @returns VBox status code. * @param pUVM The user-mode VM handle * @param pMachine The IMachine for the virtual machine. * @param pErrorMsg Pointer to the error string for VMSetError. * @param fStartPaused Whether to start it in the Paused (true) or * Running (false) state, * @param pProgress Pointer to the progress object. * @param pfPowerOffOnFailure Whether the caller should power off * the VM on failure. * * @remarks The caller expects error information to be set on failure. * @todo Check that all the possible failure paths sets error info... */ HRESULT Console::teleporterTrg(PUVM pUVM, IMachine *pMachine, Utf8Str *pErrorMsg, bool fStartPaused, Progress *pProgress, bool *pfPowerOffOnFailure) { LogThisFunc(("pUVM=%p pMachine=%p fStartPaused=%RTbool pProgress=%p\n", pUVM, pMachine, fStartPaused, pProgress)); *pfPowerOffOnFailure = true; /* * Get the config. */ ULONG uPort; HRESULT hrc = pMachine->COMGETTER(TeleporterPort)(&uPort); if (FAILED(hrc)) return hrc; ULONG const uPortOrg = uPort; Bstr bstrAddress; hrc = pMachine->COMGETTER(TeleporterAddress)(bstrAddress.asOutParam()); if (FAILED(hrc)) return hrc; Utf8Str strAddress(bstrAddress); const char *pszAddress = strAddress.isEmpty() ? NULL : strAddress.c_str(); Bstr bstrPassword; hrc = pMachine->COMGETTER(TeleporterPassword)(bstrPassword.asOutParam()); if (FAILED(hrc)) return hrc; Utf8Str strPassword(bstrPassword); strPassword.append('\n'); /* To simplify password checking. */ /* * Create the TCP server. */ int vrc; PRTTCPSERVER hServer; if (uPort) vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer); else { for (int cTries = 10240; cTries > 0; cTries--) { uPort = RTRandU32Ex(cTries >= 8192 ? 49152 : 1024, 65534); vrc = RTTcpServerCreateEx(pszAddress, uPort, &hServer); if (vrc != VERR_NET_ADDRESS_IN_USE) break; } if (RT_SUCCESS(vrc)) { hrc = pMachine->COMSETTER(TeleporterPort)(uPort); if (FAILED(hrc)) { RTTcpServerDestroy(hServer); return hrc; } } } if (RT_FAILURE(vrc)) return setError(E_FAIL, tr("RTTcpServerCreateEx failed with status %Rrc"), vrc); /* * Create a one-shot timer for timing out after 5 mins. */ RTTIMERLR hTimerLR; vrc = RTTimerLRCreateEx(&hTimerLR, 0 /*ns*/, RTTIMER_FLAGS_CPU_ANY, teleporterDstTimeout, hServer); if (RT_SUCCESS(vrc)) { vrc = RTTimerLRStart(hTimerLR, 5*60*UINT64_C(1000000000) /*ns*/); if (RT_SUCCESS(vrc)) { /* * Do the job, when it returns we're done. */ TeleporterStateTrg theState(this, pUVM, pProgress, pMachine, mControl, &hTimerLR, fStartPaused); theState.mstrPassword = strPassword; theState.mhServer = hServer; void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(&theState)); if (pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser)) { LogRel(("Teleporter: Waiting for incoming VM...\n")); hrc = pProgress->SetNextOperation(Bstr(tr("Waiting for incoming VM")).raw(), 1); if (SUCCEEDED(hrc)) { vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &theState); pProgress->setCancelCallback(NULL, NULL); if (vrc == VERR_TCP_SERVER_STOP) { vrc = theState.mRc; /* Power off the VM on failure unless the state callback already did that. */ *pfPowerOffOnFailure = false; if (RT_SUCCESS(vrc)) hrc = S_OK; else { VMSTATE enmVMState = VMR3GetStateU(pUVM); if ( enmVMState != VMSTATE_OFF && enmVMState != VMSTATE_POWERING_OFF) *pfPowerOffOnFailure = true; /* Set error. */ if (pErrorMsg->length()) hrc = setError(E_FAIL, "%s", pErrorMsg->c_str()); else hrc = setError(E_FAIL, tr("Teleporation failed (%Rrc)"), vrc); } } else if (vrc == VERR_TCP_SERVER_SHUTDOWN) { BOOL fCanceled = TRUE; hrc = pProgress->COMGETTER(Canceled)(&fCanceled); if (FAILED(hrc) || fCanceled) hrc = setError(E_FAIL, tr("Teleporting canceled")); else hrc = setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection")); LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc)); } else { hrc = setError(E_FAIL, tr("Unexpected RTTcpServerListen status code %Rrc"), vrc); LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc)); } } else LogThisFunc(("SetNextOperation failed, %Rhrc\n", hrc)); } else { LogThisFunc(("Canceled - check point #1\n")); hrc = setError(E_FAIL, tr("Teleporting canceled")); } } else hrc = setError(E_FAIL, "RTTimerLRStart -> %Rrc", vrc); RTTimerLRDestroy(hTimerLR); } else hrc = setError(E_FAIL, "RTTimerLRCreate -> %Rrc", vrc); RTTcpServerDestroy(hServer); /* * If we change TeleporterPort above, set it back to it's original * value before returning. */ if (uPortOrg != uPort) { ErrorInfoKeeper Eik; pMachine->COMSETTER(TeleporterPort)(uPortOrg); } return hrc; }