VirtualBox

Ignore:
Timestamp:
Oct 16, 2009 3:50:35 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
53583
Message:

Main: Cancellation fixes (almost perfect).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImplTeleporter.cpp

    r23810 r23827  
    240240 * @param   pState              The teleporter source state.
    241241 * @param   pszCommand          The command.
     242 * @param   fWaitForAck         Whether to wait for the ACK.
    242243 *
    243244 * @remarks the setError laziness forces this to be a Console member.
    244245 */
    245246HRESULT
    246 Console::teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand)
     247Console::teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand, bool fWaitForAck /*= true*/)
    247248{
    248249    size_t cchCommand = strlen(pszCommand);
     
    254255    if (RT_FAILURE(vrc))
    255256        return setError(E_FAIL, tr("Failed writing command '%s': %Rrc"), pszCommand, vrc);
     257    if (!fWaitForAck)
     258        return S_OK;
    256259    return teleporterSrcReadACK(pState, pszCommand);
    257260}
     
    521524        {
    522525            /* check if the failure was caused by cancellation. */
    523             BOOL fCanceled;
    524             hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCanceled);
    525             if (SUCCEEDED(hrc) && fCanceled)
     526            BOOL fCancelled;
     527            hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCancelled);
     528            if (SUCCEEDED(hrc) && fCancelled)
    526529            {
    527530                SSMR3Cancel(pState->mpVM);
     
    562565    { AutoWriteLock autoLock(); }
    563566
    564     BOOL fCanceled = TRUE;
    565     HRESULT hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCanceled);
     567    BOOL fCancelled = TRUE;
     568    HRESULT hrc = pState->mptrProgress->COMGETTER(Canceled)(&fCancelled);
    566569    if (FAILED(hrc))
    567570        return hrc;
    568     if (fCanceled)
    569         return setError(E_FAIL, tr("canceled"));
     571    if (fCancelled)
     572        return setError(E_FAIL, tr("cancelled"));
    570573
    571574    /*
     
    624627     * State fun? Automatic power off?
    625628     */
     629    if (!pState->mptrProgress->notifyPointOfNoReturn())
     630    {
     631        teleporterSrcSubmitCommand(pState, "cancel", false /*fWaitForAck*/);
     632        return E_FAIL;
     633    }
    626634    hrc = teleporterSrcSubmitCommand(pState, "done");
    627635    if (FAILED(hrc))
     
    650658        hrc = pState->mptrConsole->teleporterSrc(pState);
    651659
     660    /* (Ignore the return here as teleporterSrc deals with cancellation.) */
    652661    pState->mptrProgress->notifyComplete(hrc);
    653 
     662    pState->mptrProgress->setCancelCallback(NULL, NULL);
     663
     664    /*
     665     * Deal with the state machinery after taking the console object lock.
     666     */
    654667    AutoWriteLock autoLock(pState->mptrConsole);
    655668    if (pState->mptrConsole->mMachineState == MachineState_Saving)
     
    695708    }
    696709
     710    /*
     711     * Cleanup.
     712     */
    697713    if (pState->mhSocket != NIL_RTSOCKET)
    698714    {
     
    700716        pState->mhSocket = NIL_RTSOCKET;
    701717    }
    702 
    703     pState->mptrProgress->setCancelCallback(NULL, NULL);
    704718    delete pState;
    705719
    706     return VINF_SUCCESS;
     720    return VINF_SUCCESS; /* ignored */
    707721}
    708722
     
    847861        if (RT_SUCCESS(vrc))
    848862        {
    849             HRESULT hrc = pMachine->COMSETTER(TeleporterPort)(uPort);
     863            hrc = pMachine->COMSETTER(TeleporterPort)(uPort);
    850864            if (FAILED(hrc))
    851865            {
     
    876890
    877891            void *pvUser = static_cast<void *>(static_cast<TeleporterState *>(&State));
    878             pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser);
    879 
    880             vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &State);
    881             if (vrc == VERR_TCP_SERVER_STOP)
    882                 vrc = State.mRc;
    883             if (RT_SUCCESS(vrc))
     892            if (pProgress->setCancelCallback(teleporterProgressCancelCallback, pvUser))
    884893            {
    885                 if (fStartPaused)
    886                     setMachineState(MachineState_Paused);
     894                vrc = RTTcpServerListen(hServer, Console::teleporterTrgServeConnection, &State);
     895                pProgress->setCancelCallback(NULL, NULL);
     896
     897                bool fPowerOff = false;
     898                if (vrc == VERR_TCP_SERVER_STOP)
     899                {
     900                    vrc = State.mRc;
     901                    if (RT_SUCCESS(vrc))
     902                    {
     903                        if (fStartPaused)
     904                            setMachineState(MachineState_Paused);
     905                        else
     906                            vrc = VMR3Resume(pVM);
     907                    }
     908                    /* Power off the VM on failure unless the state callback
     909                       already did that. */
     910                    else
     911                    {
     912                        VMSTATE enmVMState = VMR3GetState(pVM);
     913                        if (    enmVMState != VMSTATE_OFF
     914                            &&  enmVMState != VMSTATE_POWERING_OFF)
     915                            fPowerOff = true;
     916                    }
     917                }
     918                else if (vrc == VERR_TCP_SERVER_SHUTDOWN)
     919                {
     920                    /** @todo this crap isn't work right wrt error info. Aaaarrrg! */
     921                    BOOL fCancelled = TRUE;
     922                    hrc = pProgress->COMGETTER(Canceled)(&fCancelled);
     923                    if (FAILED(hrc) || fCancelled)
     924                    {
     925                        setError(E_FAIL, tr("Teleporting canceled"));
     926                        vrc = VERR_SSM_CANCELLED;
     927                    }
     928                    else
     929                    {
     930                        setError(E_FAIL, tr("Teleporter timed out waiting for incoming connection"));
     931                        vrc = VERR_TIMEOUT;
     932                    }
     933                    pProgress->setResultCode(E_FAIL); /* ugly! */
     934                    LogRel(("Teleporter: RTTcpServerListen aborted - %Rrc\n", vrc));
     935                    fPowerOff = true;
     936                }
    887937                else
    888                     vrc = VMR3Resume(pVM);
     938                {
     939                    LogRel(("Teleporter: Unexpected RTTcpServerListen rc: %Rrc\n", vrc));
     940                    vrc = VERR_IPE_UNEXPECTED_STATUS;
     941                    fPowerOff = true;
     942                }
     943
     944                if (fPowerOff)
     945                {
     946                    int vrc2 = VMR3PowerOff(pVM);
     947                    AssertRC(vrc2);
     948                }
    889949            }
    890950            else
    891             {
    892                 LogRel(("Teleporter: RTTcpServerListen -> %Rrc\n", vrc));
    893             }
    894 
    895             pProgress->setCancelCallback(NULL, NULL);
     951                vrc = VERR_SSM_CANCELLED;
    896952        }
    897953
     
    935991/**
    936992 * @copydoc FNRTTCPSERVE
     993 *
     994 * @returns VINF_SUCCESS or VERR_TCP_SERVER_STOP.
    937995 */
    938996/*static*/ DECLCALLBACK(int)
     
    9531011
    9541012    /*
    955      * Password (includes '\n', see teleporterTrg).  If it's right, tell
    956      * the TCP server to stop listening (frees up host resources and makes sure
    957      * this is the last connection attempt).
     1013     * Password (includes '\n', see teleporterTrg).
    9581014     */
    9591015    const char *pszPassword = pState->mstrPassword.c_str();
     
    9771033    vrc = teleporterTcpWriteACK(pState);
    9781034    if (RT_FAILURE(vrc))
    979         return vrc;
    980 
     1035        return VINF_SUCCESS;
     1036
     1037    /*
     1038     * Stop the server and cancel the timeout timer.
     1039     *
     1040     * Note! After this point we must return VERR_TCP_SERVER_STOP, while prior
     1041     *       to it we must not return that value!
     1042     */
    9811043    RTTcpServerShutdown(pState->mhServer);
    9821044    RTTimerLRDestroy(*pState->mphTimerLR);
     
    10281090         *        maybe leave part of these to the saved state machinery?
    10291091         * Update: We're doing as much as possible in the first SSM pass. */
     1092        else if (!strcmp(szCmd, "cancel"))
     1093        {
     1094            /* Don't ACK this. */
     1095            LogRel(("Teleporter: Received cancel command.\n"));
     1096            vrc = VERR_SSM_CANCELLED;
     1097        }
    10301098        else if (!strcmp(szCmd, "done"))
    10311099        {
    1032             vrc = teleporterTcpWriteACK(pState);
     1100            /*
     1101             * The ACK is the point of no return.
     1102             */
     1103            if (pState->mptrProgress->notifyPointOfNoReturn())
     1104                vrc = teleporterTcpWriteACK(pState);
     1105            else
     1106            {
     1107                vrc = VERR_SSM_CANCELLED;
     1108                teleporterTcpWriteNACK(pState, vrc);
     1109            }
    10331110            break;
    10341111        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette