VirtualBox

Changeset 83489 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
Mar 30, 2020 4:38:23 PM (5 years ago)
Author:
vboxsync
Message:

Guest Control/Main: Fixed IGuestSession::directoryOpen() API to fail if a guest directory does not exist . bugref:9320

Location:
trunk/src/VBox/Main/src-client
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp

    r82968 r83489  
    8383        /* Start the directory process on the guest. */
    8484        GuestProcessStartupInfo procInfo;
    85         procInfo.mName      = Utf8StrFmt(tr("Reading directory \"%s\""), openInfo.mPath.c_str());
     85        procInfo.mName      = Utf8StrFmt(tr("Opening directory \"%s\""), openInfo.mPath.c_str());
    8686        procInfo.mTimeoutMS = 5 * 60 * 1000; /* 5 minutes timeout. */
    8787        procInfo.mFlags     = ProcessCreateFlag_WaitForStdOut;
     
    100100
    101101        /*
    102          * Start the process asynchronously and keep it around so that we can use
     102         * Start the process synchronously and keep it around so that we can use
    103103         * it later in subsequent read() calls.
    104          * Note: No guest rc available because operation is asynchronous.
    105104         */
    106         vrc = mData.mProcessTool.init(mSession, procInfo, true /* Async */, NULL /* Guest rc */);
    107 
    108 /** @todo r=bird: IGuest::directoryOpen need to fail if the directory doesn't
    109  *        exist like it is documented to do.  It seems this async approach or
    110  *        something is delaying such errors till GuestDirectory::read() is
    111  *        called, which is clearly messed up.
    112  */
     105        vrc = mData.mProcessTool.init(mSession, procInfo, false /* Async */, NULL /* Guest rc */);
     106        if (RT_SUCCESS(vrc))
     107        {
     108            /* As we need to know if the directory we were about to open exists and and is accessible,
     109             * do the first read here in order to return a meaningful status here. */
     110            int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
     111            vrc = i_readInternal(mData.mObjData, &rcGuest);
     112            if (RT_FAILURE(vrc))
     113            {
     114                /*
     115                 * We need to actively terminate our process tool in case of an error here,
     116                 * as this otherwise would be done on (directory) object destruction implicitly.
     117                 * This in turn then will run into a timeout, as the directory object won't be
     118                 * around anymore at that time. Ugly, but that's how it is for the moment.
     119                 */
     120                int vrcTerm = mData.mProcessTool.terminate(30 * RT_MS_1SEC, NULL /* prcGuest */);
     121                AssertRC(vrcTerm);
     122
     123                if (vrc == VERR_GSTCTL_GUEST_ERROR)
     124                    vrc = rcGuest;
     125            }
     126        }
    113127    }
    114128
     
    118132    else
    119133        autoInitSpan.setFailed();
     134
     135    LogFlowFuncLeaveRC(vrc);
    120136    return vrc;
    121137}
     
    284300
    285301/**
    286  * Reads the next directory entry.
     302 * Reads the next directory entry, internal version.
    287303 *
    288304 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available.
    289  * @param  fsObjInfo            Where to store the read directory entry.
     305 * @param  objData              Where to store the read directory entry as internal object data.
    290306 * @param  prcGuest             Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
    291307 */
    292 int GuestDirectory::i_readInternal(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *prcGuest)
     308int GuestDirectory::i_readInternal(GuestFsObjData &objData, int *prcGuest)
    293309{
    294310    AssertPtrReturn(prcGuest, VERR_INVALID_POINTER);
    295 
    296     /* Create the FS info object. */
    297     HRESULT hr = fsObjInfo.createObject();
    298     if (FAILED(hr))
    299         return VERR_COM_UNEXPECTED;
    300311
    301312    GuestProcessStreamBlock curBlock;
     
    314325            if (curBlock.GetCount()) /* Did we get content? */
    315326            {
    316                 GuestFsObjData objData;
    317                 rc = objData.FromLs(curBlock, true /* fLong */);
    318                 if (RT_SUCCESS(rc))
     327                if (curBlock.GetString("name"))
    319328                {
    320                    rc = fsObjInfo->init(objData);
     329                    rc = objData.FromLs(curBlock, true /* fLong */);
    321330                }
    322331                else
     
    335344}
    336345
     346/**
     347 * Reads the next directory entry.
     348 *
     349 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available.
     350 * @param  fsObjInfo            Where to store the read directory entry.
     351 * @param  prcGuest             Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned.
     352 */
     353int GuestDirectory::i_read(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *prcGuest)
     354{
     355    AssertPtrReturn(prcGuest, VERR_INVALID_POINTER);
     356
     357    /* Create the FS info object. */
     358    HRESULT hr = fsObjInfo.createObject();
     359    if (FAILED(hr))
     360        return VERR_COM_UNEXPECTED;
     361
     362    int rc;
     363
     364    /* If we have a valid object data cache, read from it. */
     365    if (mData.mObjData.mName.isNotEmpty())
     366    {
     367        rc = fsObjInfo->init(mData.mObjData);
     368        if (RT_SUCCESS(rc))
     369        {
     370            mData.mObjData.mName = ""; /* Mark the object data as being empty (beacon). */
     371        }
     372    }
     373    else /* Otherwise ask the guest for the next object data (block). */
     374    {
     375
     376        GuestFsObjData objData;
     377        rc = i_readInternal(objData, prcGuest);
     378        if (RT_SUCCESS(rc))
     379            rc = fsObjInfo->init(objData);
     380    }
     381
     382    LogFlowThisFunc(("Returning rc=%Rrc\n", rc));
     383    return rc;
     384}
     385
    337386/* static */
    338387HRESULT GuestDirectory::i_setErrorExternal(VirtualBoxBase *pInterface, int rcGuest)
     
    391440    ComObjPtr<GuestFsObjInfo> fsObjInfo;
    392441    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    393     int vrc = i_readInternal(fsObjInfo, &rcGuest);
     442    int vrc = i_read(fsObjInfo, &rcGuest);
    394443    if (RT_SUCCESS(vrc))
    395444    {
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r83419 r83489  
    11651165    }
    11661166
     1167    /* We need to release the write lock first before initializing the directory object below,
     1168     * as we're starting a guest process as part of it. This in turn will try to acquire the session's
     1169     * write lock. */
     1170    alock.release();
     1171
    11671172    Console *pConsole = mParent->i_getConsole();
    11681173    AssertPtr(pConsole);
     
    11701175    vrc = pDirectory->init(pConsole, this /* Parent */, idObject, openInfo);
    11711176    if (RT_FAILURE(vrc))
    1172         return vrc;
    1173 
    1174     /*
    1175      * Since this is a synchronous guest call we have to
    1176      * register the file object first, releasing the session's
    1177      * lock and then proceed with the actual opening command
    1178      * -- otherwise the file's opening callback would hang
    1179      * because the session's lock still is in place.
    1180      */
    1181     try
    1182     {
    1183         /* Add the created directory to our map. */
    1184         mData.mDirectories[idObject] = pDirectory;
    1185 
    1186         LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %zu directories)\n",
    1187                      openInfo.mPath.c_str(), mData.mSession.mID, mData.mDirectories.size()));
    1188 
    1189         alock.release(); /* Release lock before firing off event. */
    1190 
    1191         /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */
    1192     }
    1193     catch (std::bad_alloc &)
    1194     {
    1195         vrc = VERR_NO_MEMORY;
     1177    {
     1178        /* Make sure to acquire the write lock again before unregistering the object. */
     1179        alock.acquire();
     1180
     1181        int vrc2 = i_objectUnregister(idObject);
     1182        AssertRC(vrc2);
     1183
     1184        pDirectory.setNull();
     1185    }
     1186    else
     1187    {
     1188        /* Make sure to acquire the write lock again before continuing. */
     1189        alock.acquire();
     1190
     1191        try
     1192        {
     1193            /* Add the created directory to our map. */
     1194            mData.mDirectories[idObject] = pDirectory;
     1195
     1196            LogFlowFunc(("Added new guest directory \"%s\" (Session: %RU32) (now total %zu directories)\n",
     1197                         openInfo.mPath.c_str(), mData.mSession.mID, mData.mDirectories.size()));
     1198
     1199            alock.release(); /* Release lock before firing off event. */
     1200
     1201            /** @todo Fire off a VBoxEventType_OnGuestDirectoryRegistered event? */
     1202        }
     1203        catch (std::bad_alloc &)
     1204        {
     1205            vrc = VERR_NO_MEMORY;
     1206        }
    11961207    }
    11971208
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r83337 r83489  
    11101110    {
    11111111        ComObjPtr<GuestFsObjInfo> fsObjInfo;
    1112         while (RT_SUCCESS(rc = pDir->i_readInternal(fsObjInfo, &rcGuest)))
     1112        while (RT_SUCCESS(rc = pDir->i_read(fsObjInfo, &rcGuest)))
    11131113        {
    11141114            FsObjType_T enmObjType = FsObjType_Unknown; /* Shut up MSC. */
Note: See TracChangeset for help on using the changeset viewer.

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