Opened 4 months ago

Last modified 4 months ago

#9 accepted defect

Prevent nested refreshes

Reported by: erdmann Owned by: rlwalsh
Priority: major Milestone: milestone1
Component: component1 Version: 1.0
Keywords: Cc:

Description

Version 1.0.16:

Refreshing an open folder multiple times will lead to nested invocations of "wpRefresh" that compete with each other (and starting multiple refresh threads).

I suggest this change, so that "wpRefresh" will not be called nested (src\classes\xfldr.c):

SOM_Scope BOOL  SOMLINK xf_wpRefresh(XFolder *somSelf,
                                     ULONG ulView,
                                     PVOID pReserved)
{
    BOOL        rc;
    ULONG fFlags;

    // XFolderData *somThis = XFolderGetData(somSelf);
    XFolderMethodDebug("XFolder","xf_wpRefresh");

    fFlags = _wpQueryFldrFlags(somSelf);

    if (fFlags & (FOI_REFRESHINPROGRESS | FOI_POPULATEINPROGRESS))
    {
       return FALSE;
    }

   _wpModifyFldrFlags(somSelf, FOI_REFRESHINPROGRESS,FOI_REFRESHINPROGRESS);

    rc = XFolder_parent_WPFolder_wpRefresh(somSelf, ulView, pReserved);

    fdrForEachOpenInstanceView(somSelf,
                               stb_UpdateCallback,
                               2);           // update

    xthrPostWorkerMsg(WOM_REFRESHFOLDERVIEWS,
                      (MPARAM)somSelf,
                      (MPARAM)FDRUPDATE_TITLE);

   _wpModifyFldrFlags(somSelf, FOI_REFRESHINPROGRESS,0);

    return rc;
}

It might also be better to move the "_wpModifyFldrFlags(somSelf, FOI_REFRESHINPROGRESS,0);" call to the window function invoked by "xthrPostWorkerMsg" (src\filesys\xthreads.c):

MRESULT EXPENTRY fnwpWorkerObject(HWND hwndObject, ULONG msg, MPARAM 
mp1, MPARAM mp2)
{
    MRESULT mrc = NULL;

    switch (msg)
    {
...
        case WOM_REFRESHFOLDERVIEWS:
        {
            XFolder     *pFolder = NULL,
                        *pCalling = (XFolder*)(mp1);

            for ( pFolder = _wpclsQueryOpenFolders(_WPFolder, NULL, QC_FIRST, FALSE);
                  pFolder;
                  pFolder = _wpclsQueryOpenFolders(_WPFolder, pFolder, QC_NEXT, FALSE))
            {
                if (    (wpshCheckObject(pFolder))
                     && (_somIsA(pFolder, _WPFolder))
                   )
                {
                    if (    (!pCalling)
                         || (wpshResidesBelow(pFolder, pCalling))
                       )
                    {
                        // folder applies:
                        fdrUpdateAllFrameWindows(pFolder, (ULONG)mp2);
                    }
                }
            }
            if (pCalling)
            {
               _wpModifyFolderFlags(pCalling,FOI_REFRESHINPROGRESS,0);
            }
        }
        break;
...

Change History (2)

comment:1 Changed 4 months ago by erdmann

Version: 1.0

comment:2 Changed 4 months ago by rlwalsh

Owner: set to rlwalsh
Status: newaccepted

Setting FOI_REFRESHINPROGRESS before calling wpRefresh() would prevent that method from doing anything. Instead, I have designated an unused bit in the folder flags as the XWP_REFRESHINPROGRESS flag. It is set immediately before a separate thread is spun-off to invoke wpRefresh, and is cleared just before that thread terminates.

In my testing, it works as intended and prevents multiple concurrent refreshes for the same folder. This fix will appear in v1.0.17.

Note: See TracTickets for help on using tickets.