VirtualBox

Changeset 3036 in vbox for trunk/src


Ignore:
Timestamp:
Jun 4, 2007 7:19:11 PM (18 years ago)
Author:
vboxsync
Message:

XPCOM/IPC/DConnect: Fixed: Count the number of IPC references for object wrappers separately from the total number of references to avoid deletion of wrappers still being in use by the DConnect code upon client death; Fixed: Unbalanced AddRef() when processing the RELEASE client message.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp

    r2971 r3036  
    247247    return count;
    248248  }
     249
     250  // this gets called after calling AddRef() on an instance passed to the
     251  // client over IPC in order to have a count of IPC client-related references
     252  // separately from the overall reference count
     253  NS_IMETHODIMP_(nsrefcnt) AddRefIPC(void)
     254  {
     255    NS_PRECONDITION(PRInt32(mRefCntIPC) >= 0, "illegal refcnt");
     256    nsrefcnt count;
     257    count = PR_AtomicIncrement((PRInt32*)&mRefCntIPC);
     258    return count;
     259  }
     260
     261  // this gets called before calling Release() when DCON_OP_RELEASE is
     262  // received from the IPC client
     263  NS_IMETHODIMP_(nsrefcnt) ReleaseIPC(void)
     264  {
     265    NS_PRECONDITION(0 != mRefCntIPC, "dup release");
     266    nsrefcnt count;
     267    count = PR_AtomicDecrement((PRInt32 *)&mRefCntIPC);
     268    return count;
     269  }
    249270 
    250271private:
    251272  nsAutoRefCnt               mRefCnt;
     273  nsAutoRefCnt               mRefCntIPC;
    252274  PRUint32                   mPeer;  // peer process "owning" this instance
    253275  nsCOMPtr<nsIInterfaceInfo> mIInfo;
     
    259281{
    260282  for (PRInt32 i=0; i<wrappers.Count(); ++i)
     283  {
     284    ((DConnectInstance *) wrappers[i])->ReleaseIPC();
    261285    ((DConnectInstance *) wrappers[i])->Release();
     286  }
    262287}
    263288
     
    11061131
    11071132      // wrapper remains referenced when passing it to the client
    1108       // (will be released upon DCON_OP_RELEASE)
     1133      // (will be released upon DCON_OP_RELEASE). increase the
     1134      // second, IPC-only, reference counter
     1135      wrapper->AddRefIPC();
    11091136     
    11101137      // send address of the instance wrapper, and set the low bit
     
    13731400
    13741401        // wrapper remains referenced when passing it to the client
    1375         // (will be released upon DCON_OP_RELEASE)
    1376      
     1402        // (will be released upon DCON_OP_RELEASE). increase the
     1403        // second, IPC-only, reference counter
     1404        wrapper->AddRefIPC();
     1405
    13771406        // send address of the instance wrapper, and set the low bit
    13781407        // to indicate that this is an instance wrapper.
     
    26742703  if (args && args->clientID == aData->Peer())
    26752704  {
    2676     // ignore the reference counter: the client is officially dead
    2677     args->that->DeleteInstance(aData, PR_TRUE /* locked */);
     2705    // add a fake reference to hold the wrapper alive
     2706    nsrefcnt count = aData->AddRef();
     2707
     2708    // release all IPC references for this wrapper, the client is now
     2709    // officially dead (and thus cannot call AddRefIPC in the middle)
     2710    nsrefcnt countIPC = aData->AddRefIPC();
     2711    countIPC = aData->ReleaseIPC();
     2712
     2713    LOG(("ipcDConnectService::PruneInstanceMapForPeer: "
     2714         "instance=%p: %d IPC refs to release (total refcnt=%d)\n",
     2715         aData, countIPC, count));
     2716
     2717    while (countIPC)
     2718    {
     2719      countIPC = aData->ReleaseIPC();
     2720      aData->Release();
     2721    }
     2722
    26782723    // collect the instance for future destruction
    26792724    if (!args->wrappers.AppendElement(aData))
     
    27172762      }
    27182763
    2719       // destruct all instances outside the lock because it will release
    2720       // the real objects which may need to make asynchronous use our service
     2764      LOG(("ipcDConnectService::OnClientStateChange: "
     2765           "%d lost instances (should be 0 unless the peer has "
     2766           "crashed)\n", wrappers.Count()));
     2767
     2768      // release all fake references we've added in PruneInstanceMapForPeer().
     2769      // this may call wrapper destructors so it's important to do that
     2770      // outside the lock because destructors will release the real
     2771      // objects which may need to make asynchronous use our service
    27212772      for (PRInt32 i = 0; i < wrappers.Count(); ++i)
    2722         delete ((DConnectInstance *) wrappers[i]);
     2773        ((DConnectInstance *) wrappers[i])->Release();
    27232774    }
    27242775  }
     
    28762927
    28772928      // wrapper remains referenced when passing it to the client
    2878       // (will be released upon DCON_OP_RELEASE)
     2929      // (will be released upon DCON_OP_RELEASE). increase the
     2930      // second, IPC-only, reference counter
     2931      wrapper->AddRefIPC();
    28792932    }
    28802933  }
     
    29473000  if (mInstanceSet.Contains(wrapper))
    29483001  {
     3002    // add a fake reference to hold the wrapper alive
    29493003    nsrefcnt count = wrapper->AddRef();
     3004
     3005    // release references
     3006    nsrefcnt countIPC = wrapper->ReleaseIPC();
    29503007    count = wrapper->Release();
     3008
     3009    NS_ASSERTION(count > 0, "unbalanced AddRef()/Release()");
     3010
    29513011    if (count == 1)
    29523012    {
     3013      NS_ASSERTION(countIPC == 0, "unbalanced AddRefIPC()/ReleaseIPC()");
     3014
    29533015      // we are the last one who holds a (fake) reference, remove the
    29543016      // instace from instance maps while still under the lock
    29553017      DeleteInstance(wrapper, PR_TRUE /* locked */);
     3018
    29563019      // leave the lock before calling the destructor because it will release
    29573020      // the real object which may need to make asynchronous use our service
    29583021      lock.unlock();
    29593022      delete wrapper;
     3023    }
     3024    else
     3025    {
     3026      // release the fake reference
     3027      wrapper->Release();
    29603028    }
    29613029  }
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