VirtualBox

Changeset 23827 in vbox for trunk/src


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).

Location:
trunk/src/VBox/Main
Files:
5 edited

Legend:

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

    r23810 r23827  
    67626762                }
    67636763                else if (task->mTeleporterEnabled)
    6764                 {
    67656764                    /* -> ConsoleImplTeleporter.cpp */
    67666765                    vrc = console->teleporterTrg(pVM, pMachine, task->mStartPaused, task->mProgress);
    6767                     if (RT_FAILURE(vrc))
    6768                         VMR3PowerOff(pVM);
    6769                 }
    67706766                else if (task->mStartPaused)
    67716767                    /* done */
  • 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        }
  • trunk/src/VBox/Main/ProgressImpl.cpp

    r23810 r23827  
    514514
    515515/**
    516  * Sets the cancellation callback.
     516 * Sets the cancelation callback, checking for cancelation first.
     517 *
     518 * @returns Success indicator.
     519 * @retval  true on success.
     520 * @retval  false if the progress object has already been canceled or is in an
     521 *          invalid state
    517522 *
    518523 * @param   pfnCallback     The function to be called upon cancelation.
    519524 * @param   pvUser          The callback argument.
    520525 */
    521 void ProgressBase::setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
    522 {
    523     AutoCaller autoCaller(this);
    524     AssertComRCReturnVoid(autoCaller.rc());
    525 
    526     AutoWriteLock alock(this);
     526bool ProgressBase::setCancelCallback(void (*pfnCallback)(void *), void *pvUser)
     527{
     528    AutoCaller autoCaller(this);
     529    AssertComRCReturn(autoCaller.rc(), false);
     530
     531    AutoWriteLock alock(this);
     532
     533    if (mCanceled)
     534        return false;
    527535
    528536    m_pvCancelUserArg   = pvUser;
    529537    m_pfnCancelCallback = pfnCallback;
    530 }
    531 
     538    return true;
     539}
    532540
    533541////////////////////////////////////////////////////////////////////////////////
     
    11411149}
    11421150
     1151/**
     1152 * Notify the progress object that we're almost at the point of no return.
     1153 *
     1154 * This atomically checks for and disables cancelation.  Calls to
     1155 * IProgress::Cancel() made after a successfull call to this method will fail
     1156 * and the user can be told.  While this isn't entirely clean behavior, it
     1157 * prevents issues with an irreversible actually operation succeeding while the
     1158 * user belive it was rolled back.
     1159 *
     1160 * @returns Success indicator.
     1161 * @retval  true on success.
     1162 * @retval  false if the progress object has already been canceled or is in an
     1163 *          invalid state
     1164 */
     1165bool Progress::notifyPointOfNoReturn(void)
     1166{
     1167    AutoCaller autoCaller(this);
     1168    AssertComRCReturn(autoCaller.rc(), false);
     1169
     1170    AutoWriteLock alock(this);
     1171
     1172    if (mCanceled)
     1173        return false;
     1174
     1175    mCancelable = FALSE;
     1176    return true;
     1177}
     1178
    11431179////////////////////////////////////////////////////////////////////////////////
    11441180// CombinedProgress class
     
    15911627
    15921628    if (!mCancelable)
    1593         return setError (E_FAIL, tr ("Operation cannot be cancelled"));
     1629        return setError (E_FAIL, tr ("Operation cannot be canceled"));
    15941630
    15951631    if (!mCanceled)
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r23810 r23827  
    522522    HRESULT                     teleporterSrc(TeleporterStateSrc *pState);
    523523    HRESULT                     teleporterSrcReadACK(TeleporterStateSrc *pState, const char *pszWhich, const char *pszNAckMsg = NULL);
    524     HRESULT                     teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand);
     524    HRESULT                     teleporterSrcSubmitCommand(TeleporterStateSrc *pState, const char *pszCommand, bool fWaitForAck = true);
    525525    int                         teleporterTrg(PVM pVM, IMachine *pMachine, bool fStartPaused, Progress *pProgress);
    526526    static DECLCALLBACK(int)    teleporterTrgServeConnection(RTSOCKET Sock, void *pvUser);
  • trunk/src/VBox/Main/include/ProgressImpl.h

    r23810 r23827  
    8686
    8787    static HRESULT setErrorInfoOnThread (IProgress *aProgress);
    88     void setCancelCallback(void (*pfnCallback)(void *), void *pvUser);
     88    bool setCancelCallback(void (*pfnCallback)(void *), void *pvUser);
    8989
    9090
     
    266266                           const Bstr &aComponent,
    267267                           const char *aText, ...);
     268    bool notifyPointOfNoReturn(void);
    268269
    269270    /** For com::SupportErrorInfoImpl. */
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