VirtualBox

Changeset 2499 in vbox


Ignore:
Timestamp:
May 4, 2007 4:49:18 PM (18 years ago)
Author:
vboxsync
Message:

XPCOM/IPC/DConnect: Attempted to fix a race condition when deleting instance wrappers introduced by changeset:20849.

Location:
trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src
Files:
2 edited

Legend:

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

    r2440 r2499  
    239239      nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
    240240      if (dConnect)
    241           dConnect->DeleteInstance(this);
     241        dConnect->DeleteInstance(this);
    242242      else
    243           NS_NOTREACHED("ipcDConnectService has gone before DConnectInstance");
     243        NS_NOTREACHED("ipcDConnectService has gone before DConnectInstance");
    244244      delete this;
    245245      return 0;
     
    22232223  // disregarding the reference counter
    22242224   
     2225#ifdef IPC_LOGGING
     2226  const char *name;
     2227  aData->InterfaceInfo()->GetNameShared(&name);
     2228  LOG(("ipcDConnectService: WARNING: deleting unreleased "
     2229       "instance=%p iface=%p {%s}\n", aData, aData->RealInstance(), name));
     2230#endif
     2231
    22252232  delete aData;
    22262233  return PL_DHASH_NEXT;
     
    24242431
    24252432void
    2426 ipcDConnectService::DeleteInstance(DConnectInstance *wrapper)
    2427 {
     2433ipcDConnectService::DeleteInstance(DConnectInstance *wrapper,
     2434                                   PRBool locked /* = PR_FALSE */)
     2435{
     2436  if (!locked)
     2437    PR_Lock(mLock);
     2438
    24282439#ifdef IPC_LOGGING
    24292440  const char *name;
     
    24332444#endif
    24342445
    2435   {
    2436     nsAutoLock lock (mLock);
    2437 
    2438     mInstances.Remove(wrapper->GetKey());
    2439     mInstanceSet.Remove(wrapper);
    2440   }
     2446  mInstances.Remove(wrapper->GetKey());
     2447  mInstanceSet.Remove(wrapper);
     2448
     2449  if (!locked)
     2450    PR_Unlock(mLock);
    24412451}
    24422452
     
    26482658struct PruneInstanceMapForPeerArgs
    26492659{
     2660  ipcDConnectService *that;
    26502661  PRUint32 clientID;
    2651   DConnectInstanceMap &instances;
    2652   DConnectInstanceSet &instanceSet;
     2662  nsVoidArray &wrappers;
    26532663};
    26542664
     
    26632673  if (args && args->clientID == aData->Peer())
    26642674  {
    2665 #ifdef IPC_LOGGING
    2666     const char *name;
    2667     aData->InterfaceInfo()->GetNameShared(&name);
    2668     LOG(("PruneInstanceMapForClient(): instance=%p iface=%p {%s} peer=%d\n",
    2669          aData, aData->RealInstance(), name, args->clientID));
    2670 #endif
    2671     args->instances.Remove(aKey);
    2672     args->instanceSet.Remove(aData);
    2673     /* ignore the reference counter: the client is officially dead */
    2674     delete aData;
     2675    // ignore the reference counter: the client is officially dead
     2676    args->that->DeleteInstance(aData, PR_TRUE /* locked */);
     2677    // collect the instance for future destruction
     2678    if (!args->wrappers.AppendElement(aData))
     2679    {
     2680      NS_NOTREACHED("Not enough memory");
     2681      // bad but what to do
     2682      delete aData;
     2683    }
    26752684  }
    26762685  return PL_DHASH_NEXT;
     
    26972706           "pruning all instances created for peer %d...\n", aClientID));
    26982707
    2699       nsAutoLock lock (mLock);
    2700 
    2701       // make sure we have released all instances
    2702       PruneInstanceMapForPeerArgs args = { aClientID, mInstances, mInstanceSet };
    2703       mInstances.EnumerateRead(PruneInstanceMapForPeer, (void *)&args);
     2708      nsVoidArray wrappers;
     2709
     2710      {
     2711        nsAutoLock lock (mLock);
     2712
     2713        // make sure we have removed all instances from instance maps
     2714        PruneInstanceMapForPeerArgs args = { this, aClientID, wrappers };
     2715        mInstances.EnumerateRead(PruneInstanceMapForPeer, (void *)&args);
     2716      }
     2717
     2718      // destruct all instances outside the lock because it will release
     2719      // the real objects which may need to make asynchronous use our service
     2720      for (PRInt32 i = 0; i < wrappers.Count(); ++i)
     2721        delete ((DConnectInstance *) wrappers[i]);
    27042722    }
    27052723  }
     
    29212939       peer, release->instance));
    29222940
     2941  DConnectInstance *wrapper = release->instance;
     2942
     2943  nsAutoLock lock (mLock);
     2944
    29232945  // make sure we've been sent a valid wrapper
    2924   if (CheckInstanceAndAddRef(release->instance))
    2925   {
    2926     // release twice: once to balance CheckInstanceAndAddRef() and once
    2927     // to satisfy the RELEASE request (the instance is no more needed by
    2928     // this peer)
    2929     release->instance->Release();
    2930     release->instance->Release();
     2946  if (mInstanceSet.Contains(wrapper))
     2947  {
     2948    nsrefcnt count = wrapper->AddRef();
     2949    count = wrapper->Release();
     2950    if (count == 1)
     2951    {
     2952      // we are the last one who holds a (fake) reference, remove the
     2953      // instace from instance maps while still under the lock
     2954      DeleteInstance(wrapper, PR_TRUE /* locked */);
     2955      // leave the lock before calling the destructor because it will release
     2956      // the real object which may need to make asynchronous use our service
     2957      lock.unlock();
     2958      delete wrapper;
     2959    }
    29312960  }
    29322961  else
    29332962  {
    2934     NS_NOTREACHED("instance wrapper not found");
     2963    // it is possible that the client disconnection event handler has released
     2964    // all client instances before the RELEASE message sent by the client gets
     2965    // processed here. Just give a warning
     2966    LOG(("ipcDConnectService::OnRelease: WARNING: instance wrapper not found"));
    29352967  }
    29362968}
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h

    r2093 r2499  
    233233
    234234  // public only for DConnectInstance::Release()
    235   NS_HIDDEN_(void)     DeleteInstance(DConnectInstance *);
     235  NS_HIDDEN_(void)     DeleteInstance(DConnectInstance *, PRBool locked = PR_FALSE);
    236236  // public only for DConnectStub::CallMethod()
    237237  NS_HIDDEN_(PRBool)   CheckInstanceAndAddRef(DConnectInstance *);
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