VirtualBox

Ignore:
Timestamp:
Feb 16, 2010 3:01:50 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
57768
Message:

XPCOM: fix IPC message processing in the situation where several threads call the same client which then crashes. Before only one thread got the client death message, and the others would hang forever. Essentially added code which keeps track of the client state. r57733 was too paranoid, and failed more or less frequently when VBoxSVC was autostarted.

File:
1 edited

Legend:

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

    r26566 r26582  
    5151#include "nsDeque.h"
    5252#include "xptcall.h"
     53
     54#ifdef VBOX
     55#include <map>
     56#include <list>
     57#endif /* VBOX */
    5358
    5459#if defined(DCONNECT_MULTITHREADED)
     
    12551260//-----------------------------------------------------------------------------
    12561261
     1262#ifdef VBOX
     1263typedef struct ClientDownInfo
     1264{
     1265    ClientDownInfo(PRUint32 aClient)
     1266    {
     1267        uClient = aClient;
     1268        uTimestamp = PR_IntervalNow();
     1269    }
     1270
     1271    PRUint32 uClient;
     1272    PRIntervalTime uTimestamp;
     1273} ClientDownInfo;
     1274typedef std::map<PRUint32, ClientDownInfo *> ClientDownMap;
     1275typedef std::list<ClientDownInfo *> ClientDownList;
     1276
     1277#define MAX_CLIENT_DOWN_SIZE 10000
     1278
     1279/* Protected by the queue monitor. */
     1280static ClientDownMap g_ClientDownMap;
     1281static ClientDownList g_ClientDownList;
     1282
     1283#endif /* VBOX */
     1284
    12571285class DConnectMsgSelector : public ipcIMessageObserver
    12581286{
     
    12751303    // accept special "client dead" messages for a given peer
    12761304    // (empty target id, zero data and data length)
     1305#ifndef VBOX
    12771306    if (aSenderID == mPeer && aTarget.Equals(nsID()) && !aData && !aDataLen)
    12781307        return NS_OK;
     1308#else /* VBOX */
     1309    if (aSenderID != IPC_SENDER_ANY && aTarget.Equals(nsID()) && !aData && !aDataLen)
     1310    {
     1311        // Insert new client down information. Start by expiring outdated
     1312        // entries and free one element if there's still no space (if needed).
     1313        PRIntervalTime now = PR_IntervalNow();
     1314        do {
     1315            ClientDownInfo *cInfo = g_ClientDownList.back();
     1316            if (!cInfo)
     1317                break;
     1318            PRInt64 diff = (PRInt64)now - cInfo->uTimestamp;
     1319            if (diff < 0)
     1320                diff += (PRInt64)((PRIntervalTime)-1) + 1;
     1321            if (diff > PR_SecondsToInterval(15 * 60))
     1322            {
     1323                g_ClientDownMap.erase(cInfo->uClient);
     1324                g_ClientDownList.pop_back();
     1325                delete cInfo;
     1326            }
     1327            else
     1328                break;
     1329        } while (true);
     1330
     1331        ClientDownMap::iterator it = g_ClientDownMap.find(aSenderID);
     1332        if (it == g_ClientDownMap.end())
     1333        {
     1334            while (g_ClientDownList.size() >= MAX_CLIENT_DOWN_SIZE)
     1335            {
     1336                ClientDownInfo *cInfo = g_ClientDownList.back();
     1337                g_ClientDownMap.erase(cInfo->uClient);
     1338                g_ClientDownList.pop_back();
     1339                delete cInfo;
     1340            }
     1341
     1342            ClientDownInfo *cInfo = new ClientDownInfo(aSenderID);
     1343            g_ClientDownMap[aSenderID] = cInfo;
     1344            g_ClientDownList.push_front(cInfo);
     1345        }
     1346        return (aSenderID == mPeer) ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
     1347    }
     1348    // accept special "client up" messages for a given peer
     1349    // (empty target id, zero data and data length=1)
     1350    if (aTarget.Equals(nsID()) && !aData && aDataLen == 1)
     1351    {
     1352        ClientDownMap::iterator it = g_ClientDownMap.find(aSenderID);
     1353        if (it != g_ClientDownMap.end())
     1354        {
     1355            ClientDownInfo *cInfo = it->second;
     1356            g_ClientDownMap.erase(it);
     1357            g_ClientDownList.remove(cInfo);
     1358            delete cInfo;
     1359        }
     1360        return (aSenderID == mPeer) ? NS_OK : IPC_WAIT_NEXT_MESSAGE;
     1361    }
     1362    // accept special "client check" messages for an anonymous sender
     1363    // (invalid sender id, empty target id, zero data and data length
     1364    if (aSenderID == IPC_SENDER_ANY && aTarget.Equals(nsID()) && !aData && !aDataLen)
     1365    {
     1366        LOG(("DConnectMsgSelector::OnMessageAvailable: poll liveness for mPeer=%d\n",
     1367             mPeer));
     1368        ClientDownMap::iterator it = g_ClientDownMap.find(mPeer);
     1369        return (it == g_ClientDownMap.end()) ? IPC_WAIT_NEXT_MESSAGE : NS_OK;
     1370    }
     1371#endif /* VBOX */
    12791372    const DConnectOp *op = (const DConnectOp *) aData;
    12801373    // accept only reply messages with the given peer/opcode/index
Note: See TracChangeset for help on using the changeset viewer.

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