VirtualBox

Changeset 52369 in vbox


Ignore:
Timestamp:
Aug 13, 2014 5:18:30 PM (10 years ago)
Author:
vboxsync
Message:

XPCOM library: do not wait for worker threads too long on com::Shutdown(); just give them a chance to terminate within reasonable time and abandon them after timeout.

File:
1 edited

Legend:

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

    r46435 r52369  
    5858# include <iprt/req.h>
    5959# include <iprt/mem.h>
     60# include <iprt/time.h>
     61# include <iprt/thread.h>
    6062#endif /* VBOX */
    6163
     
    131133// DCON_OP_SETUP_REPLY and DCON_OP_INVOKE_REPLY flags
    132134#define DCON_OP_FLAGS_REPLY_EXCEPTION   0x0001
     135
     136// Within this time all the worker threads must be terminated.
     137#define VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS  (5000)
    133138
    134139#pragma pack(1)
     
    29022907  NS_DECL_NSIRUNNABLE
    29032908
    2904   DConnectWorker(ipcDConnectService *aDConnect) : mDConnect (aDConnect) {}
     2909  DConnectWorker(ipcDConnectService *aDConnect) : mDConnect (aDConnect), mIsRunnable (PR_FALSE) {}
    29052910  NS_HIDDEN_(nsresult) Init();
    29062911  NS_HIDDEN_(void) Join() { mThread->Join(); };
     2912  NS_HIDDEN_(bool) IsRunning() { return mIsRunnable; };
    29072913
    29082914private:
    29092915  nsCOMPtr <nsIThread> mThread;
    29102916  ipcDConnectService *mDConnect;
     2917
     2918  // Indicate if thread might be quickly joined on shutdown.
     2919  volatile bool mIsRunnable;
    29112920};
    29122921
     
    29232932{
    29242933  LOG(("DConnect Worker thread started.\n"));
     2934
     2935  mIsRunnable = PR_TRUE;
    29252936
    29262937  nsAutoMonitor mon(mDConnect->mPendingMon);
     
    29722983    }
    29732984  }
     2985
     2986  mIsRunnable = PR_FALSE;
    29742987
    29752988  LOG(("DConnect Worker thread stopped.\n"));
     
    31923205#endif
    31933206
    3194   // destroy all worker threads
    3195   for (int i = 0; i < mWorkers.Count(); i++)
    3196   {
    3197     DConnectWorker *worker = NS_STATIC_CAST(DConnectWorker *, mWorkers[i]);
    3198     worker->Join();
    3199     delete worker;
    3200   }
     3207
     3208  // Iterate over currently running worker threads
     3209  // during VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS, join() those who
     3210  // exited a working loop and abandon ones which have not
     3211  // managed to do that when timeout occurred.
     3212  LOG(("Worker threads: %d\n", mWorkers.Count()));
     3213  uint64_t tsStart = RTTimeMilliTS();
     3214  while ((tsStart + VBOX_XPCOM_SHUTDOWN_TIMEOUT_MS ) > RTTimeMilliTS() && mWorkers.Count() > 0)
     3215  {
     3216    // Some array elements might be deleted while iterating. Going from the last
     3217    // to the first array element (intentionally) in order to do not conflict with
     3218    // array indexing once element is deleted.
     3219    for (int i = mWorkers.Count() - 1; i >= 0; i--)
     3220    {
     3221      DConnectWorker *worker = NS_STATIC_CAST(DConnectWorker *, mWorkers[i]);
     3222      if (worker->IsRunning() == PR_FALSE)
     3223      {
     3224        LOG(("Worker %p joined.\n", worker));
     3225        worker->Join();
     3226        delete worker;
     3227        mWorkers.RemoveElementAt(i);
     3228      }
     3229    }
     3230
     3231    // Relax a bit before the next round.
     3232    RTThreadSleep(10);
     3233  }
     3234
     3235  LOG(("There are %d thread(s) left.\n", mWorkers.Count()));
     3236
     3237  // If there are some running threads left, just forget about them.
    32013238  mWorkers.Clear();
    32023239
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