VirtualBox

Changeset 2093 in vbox for trunk/src/libs/xpcom18a4/ipc/ipcd


Ignore:
Timestamp:
Apr 16, 2007 11:38:48 AM (18 years ago)
Author:
vboxsync
Message:

Committed back changeset:20231 to find out the exact problem on test boxes (couldn't reproduce locally).

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

    r1964 r2093  
    2121 * Contributor(s):
    2222 *   Darin Fisher <[email protected]>
     23 *   Dmitry A. Kuminov <[email protected]>
    2324 *
    2425 * Alternatively, the contents of this file may be used under the terms of
     
    4546#include "nsIInterfaceInfoManager.h"
    4647#include "nsIExceptionService.h"
    47 #include "nsAutoPtr.h"
    4848#include "nsString.h"
    4949#include "nsVoidArray.h"
     
    158158  DConAddr instance;
    159159  nsresult status;
     160  // followed by a specially serialized nsIException instance if
     161  // NS_FAILED(status) (see ipcDConnectService::SerializeException)
    160162};
    161163
     
    181183{
    182184  nsresult result;
    183   // followed by an array of out-param blobs if NS_SUCCEEDED (result)
    184   // or by an nsIException instance if NS_FAILED (result) and the called
    185   // method has set an exception for the current thread using nsIExceptionManager
     185  // followed by an array of out-param blobs if NS_SUCCEEDED(result), or by a
     186  // specially serialized nsIException instance if NS_FAILED(result)
     187  // (see ipcDConnectService::SerializeException)
    186188};
    187189
     
    11161118}
    11171119
     1120//-----------------------------------------------------------------------------
     1121
     1122#define EXCEPTION_STUB_ID                          \
     1123{ /* 70578d68-b25e-4370-a70c-89bbe56e6699 */       \
     1124  0x70578d68,                                      \
     1125  0xb25e,                                          \
     1126  0x4370,                                          \
     1127  {0xa7, 0x0c, 0x89, 0xbb, 0xe5, 0x6e, 0x66, 0x99} \
     1128}
     1129static NS_DEFINE_IID(kExceptionStubID, EXCEPTION_STUB_ID);
     1130
     1131// ExceptionStub is used to cache all primitive-typed bits of a remote nsIException
     1132// instance (such as the error message or line number) to:
     1133//
     1134// a) reduce the number of IPC calls;
     1135// b) make sure exception information is available to the calling party even if
     1136//    the called party terminates immediately after returning an exception.
     1137//    To achieve this, all cacheable information is serialized together with
     1138//    the instance wrapper itself.
     1139
     1140class ExceptionStub : public nsIException
     1141{
     1142public:
     1143
     1144  NS_DECL_ISUPPORTS
     1145  NS_DECL_NSIEXCEPTION
     1146
     1147  ExceptionStub(const nsACString &aMessage, nsresult aResult,
     1148                const nsACString &aName, const nsACString &aFilename,
     1149                PRUint32 aLineNumber, PRUint32 aColumnNumber,
     1150                DConnectStub *aXcptStub)
     1151    : mMessage(aMessage), mResult(aResult)
     1152    , mName(aName), mFilename(aFilename)
     1153    , mLineNumber (aLineNumber), mColumnNumber (aColumnNumber)
     1154    , mXcptStub (aXcptStub) { NS_ASSERTION(aXcptStub, "NULL"); }
     1155
     1156  ~ExceptionStub() {}
     1157
     1158  nsIException *Exception() { return (nsIException *)(nsISupports *) mXcptStub; }
     1159  DConnectStub *Stub() { return mXcptStub; }
     1160
     1161private:
     1162
     1163  nsCString mMessage;
     1164  nsresult mResult;
     1165  nsCString mName;
     1166  nsCString mFilename;
     1167  PRUint32 mLineNumber;
     1168  PRUint32 mColumnNumber;
     1169  nsRefPtr<DConnectStub> mXcptStub;
     1170};
     1171
     1172NS_IMPL_ADDREF(ExceptionStub)
     1173NS_IMPL_RELEASE(ExceptionStub)
     1174
     1175NS_IMETHODIMP
     1176ExceptionStub::QueryInterface(const nsID &aIID, void **aInstancePtr)
     1177{
     1178  NS_ASSERTION(aInstancePtr,
     1179               "QueryInterface requires a non-NULL destination!");
     1180
     1181  // used to discover if this is an ExceptionStub instance.
     1182  if (aIID.Equals(kExceptionStubID))
     1183  {
     1184    *aInstancePtr = this;
     1185    NS_ADDREF_THIS();
     1186    return NS_OK;
     1187  }
     1188
     1189  // regular NS_IMPL_QUERY_INTERFACE1 sequence
     1190
     1191  nsISupports* foundInterface = 0;
     1192
     1193  if (aIID.Equals(NS_GET_IID(nsIException)))
     1194    foundInterface = NS_STATIC_CAST(nsIException*, this);
     1195  else
     1196  if (aIID.Equals(NS_GET_IID(nsISupports)))
     1197    foundInterface = NS_STATIC_CAST(nsISupports*,
     1198                                    NS_STATIC_CAST(nsIException *, this));
     1199  else
     1200  if (mXcptStub)
     1201  {
     1202    // ask the real nsIException object
     1203    return mXcptStub->QueryInterface(aIID, aInstancePtr);
     1204  }
     1205
     1206  nsresult status;
     1207  if (!foundInterface)
     1208    status = NS_NOINTERFACE;
     1209  else
     1210  {
     1211    NS_ADDREF(foundInterface);
     1212    status = NS_OK;
     1213  }
     1214  *aInstancePtr = foundInterface;
     1215  return status;
     1216}
     1217
     1218/* readonly attribute string message; */
     1219NS_IMETHODIMP ExceptionStub::GetMessage(char **aMessage)
     1220{
     1221  if (!aMessage)
     1222    return NS_ERROR_INVALID_POINTER;
     1223  *aMessage = ToNewCString(mMessage);
     1224  return NS_OK;
     1225}
     1226
     1227/* readonly attribute nsresult result; */
     1228NS_IMETHODIMP ExceptionStub::GetResult(nsresult *aResult)
     1229{
     1230  if (!aResult)
     1231    return NS_ERROR_INVALID_POINTER;
     1232  *aResult = mResult;
     1233  return NS_OK;
     1234}
     1235
     1236/* readonly attribute string name; */
     1237NS_IMETHODIMP ExceptionStub::GetName(char **aName)
     1238{
     1239  if (!aName)
     1240    return NS_ERROR_INVALID_POINTER;
     1241  *aName = ToNewCString(mName);
     1242  return NS_OK;
     1243}
     1244
     1245/* readonly attribute string filename; */
     1246NS_IMETHODIMP ExceptionStub::GetFilename(char **aFilename)
     1247{
     1248  if (!aFilename)
     1249    return NS_ERROR_INVALID_POINTER;
     1250  *aFilename = ToNewCString(mFilename);
     1251  return NS_OK;
     1252}
     1253
     1254/* readonly attribute PRUint32 lineNumber; */
     1255NS_IMETHODIMP ExceptionStub::GetLineNumber(PRUint32 *aLineNumber)
     1256{
     1257  if (!aLineNumber)
     1258    return NS_ERROR_INVALID_POINTER;
     1259  *aLineNumber = mLineNumber;
     1260  return NS_OK;
     1261}
     1262
     1263/* readonly attribute PRUint32 columnNumber; */
     1264NS_IMETHODIMP ExceptionStub::GetColumnNumber(PRUint32 *aColumnNumber)
     1265{
     1266  if (!aColumnNumber)
     1267    return NS_ERROR_INVALID_POINTER;
     1268  *aColumnNumber = mColumnNumber;
     1269  return NS_OK;
     1270}
     1271
     1272/* readonly attribute nsIStackFrame location; */
     1273NS_IMETHODIMP ExceptionStub::GetLocation(nsIStackFrame **aLocation)
     1274{
     1275  if (Exception())
     1276    return Exception()->GetLocation (aLocation);
     1277  return NS_ERROR_UNEXPECTED;
     1278}
     1279
     1280/* readonly attribute nsIException inner; */
     1281NS_IMETHODIMP ExceptionStub::GetInner(nsIException **aInner)
     1282{
     1283  if (Exception())
     1284    return Exception()->GetInner (aInner);
     1285  return NS_ERROR_UNEXPECTED;
     1286}
     1287
     1288/* readonly attribute nsISupports data; */
     1289NS_IMETHODIMP ExceptionStub::GetData(nsISupports * *aData)
     1290{
     1291  if (Exception())
     1292    return Exception()->GetData (aData);
     1293  return NS_ERROR_UNEXPECTED;
     1294}
     1295
     1296/* string toString (); */
     1297NS_IMETHODIMP ExceptionStub::ToString(char **_retval)
     1298{
     1299  if (Exception())
     1300    return Exception()->ToString (_retval);
     1301  return NS_ERROR_UNEXPECTED;
     1302}
     1303
     1304nsresult
     1305ipcDConnectService::SerializeException(ipcMessageWriter &writer,
     1306                                       PRUint32 peer, nsIException *xcpt,
     1307                                       nsVoidArray &wrappers)
     1308{
     1309  PRBool cache_fields = PR_FALSE;
     1310
     1311  // first, seralize the nsIException pointer.  The code is merely the same as
     1312  // in SerializeInterfaceParam() except that when the exception to serialize
     1313  // is an ExceptionStub instance and the real instance it stores as mXcpt
     1314  // is a DConnectStub corresponding to an object in the address space of the
     1315  // peer, we simply pass that object back instead of creating a new wrapper.
     1316
     1317  {
     1318    nsAutoLock lock (mLock);
     1319
     1320    if (mDisconnected)
     1321      return NS_ERROR_NOT_INITIALIZED;
     1322
     1323    if (!xcpt)
     1324    {
     1325      // write null address
     1326      writer.PutBytes(&xcpt, sizeof(xcpt));
     1327    }
     1328    else
     1329    {
     1330      ExceptionStub *stub = nsnull;
     1331      nsresult rv = xcpt->QueryInterface(kExceptionStubID, (void **) &stub);
     1332      if (NS_SUCCEEDED(rv) && (stub->Stub()->PeerID() == peer))
     1333      {
     1334        // send the wrapper instance back to the peer
     1335        void *p = stub->Stub()->Instance();
     1336        writer.PutBytes(&p, sizeof(p));
     1337      }
     1338      else
     1339      {
     1340        // create instance wrapper
     1341
     1342        const nsID &iid = nsIException::GetIID();
     1343        nsCOMPtr<nsIInterfaceInfo> iinfo;
     1344        rv = GetInterfaceInfo(iid, getter_AddRefs(iinfo));
     1345        if (NS_FAILED(rv))
     1346          return rv;
     1347
     1348        DConnectInstance *wrapper = nsnull;
     1349
     1350        // first try to find an existing wrapper for the given object
     1351        if (!FindInstanceAndAddRef(peer, xcpt, &iid, &wrapper))
     1352        {
     1353          wrapper = new DConnectInstance(peer, iinfo, xcpt);
     1354          if (!wrapper)
     1355            return NS_ERROR_OUT_OF_MEMORY;
     1356
     1357          rv = StoreInstance(wrapper);
     1358          if (NS_FAILED(rv))
     1359          {
     1360            delete wrapper;
     1361            return rv;
     1362          }
     1363
     1364          // reference the newly created wrapper
     1365          wrapper->AddRef();
     1366        }
     1367       
     1368        if (!wrappers.AppendElement(wrapper))
     1369        {
     1370          wrapper->Release();
     1371          return NS_ERROR_OUT_OF_MEMORY;
     1372        }
     1373
     1374        // wrapper remains referenced when passing it to the client
     1375        // (will be released upon DCON_OP_RELEASE)
     1376     
     1377        // send address of the instance wrapper, and set the low bit
     1378        // to indicate that this is an instance wrapper.
     1379        PtrBits bits = ((PtrBits) wrapper) | 0x1;
     1380        writer.PutBytes(&bits, sizeof(bits));
     1381
     1382        // we want to cache fields to minimize the number of IPC calls when
     1383        // accessing exception data on the peer side
     1384        cache_fields = PR_TRUE;
     1385      }
     1386      NS_IF_RELEASE(stub);
     1387    }
     1388  }
     1389
     1390  if (!cache_fields)
     1391    return NS_OK;
     1392
     1393  nsresult rv;
     1394  nsXPIDLCString str;
     1395  PRUint32 num;
     1396
     1397  // message
     1398  rv = xcpt->GetMessage(getter_Copies(str));
     1399  if (NS_SUCCEEDED (rv))
     1400  {
     1401    PRUint32 len = str.Length();
     1402    nsACString::const_iterator begin;
     1403    const char *data = str.BeginReading(begin).get();
     1404    writer.PutInt32(len);
     1405    writer.PutBytes(data, len);
     1406  }
     1407  else
     1408    writer.PutInt32(0);
     1409
     1410  // result
     1411  nsresult res = 0;
     1412  xcpt->GetResult(&res);
     1413  writer.PutInt32(res);
     1414
     1415  // name
     1416  rv = xcpt->GetName(getter_Copies(str));
     1417  if (NS_SUCCEEDED (rv))
     1418  {
     1419    PRUint32 len = str.Length();
     1420    nsACString::const_iterator begin;
     1421    const char *data = str.BeginReading(begin).get();
     1422    writer.PutInt32(len);
     1423    writer.PutBytes(data, len);
     1424  }
     1425  else
     1426    writer.PutInt32(0);
     1427
     1428  // filename
     1429  rv = xcpt->GetFilename(getter_Copies(str));
     1430  if (NS_SUCCEEDED (rv))
     1431  {
     1432    PRUint32 len = str.Length();
     1433    nsACString::const_iterator begin;
     1434    const char *data = str.BeginReading(begin).get();
     1435    writer.PutInt32(len);
     1436    writer.PutBytes(data, len);
     1437  }
     1438  else
     1439    writer.PutInt32(0);
     1440
     1441  // lineNumber
     1442  num = 0;
     1443  xcpt->GetLineNumber(&num);
     1444  writer.PutInt32(num);
     1445
     1446  // columnNumber
     1447  num = 0;
     1448  xcpt->GetColumnNumber(&num);
     1449  writer.PutInt32(num);
     1450
     1451  return writer.HasError() ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
     1452}
     1453
     1454nsresult
     1455ipcDConnectService::DeserializeException(const PRUint8 *data,
     1456                                         PRUint32 dataLen,
     1457                                         PRUint32 peer,
     1458                                         nsIException **xcpt)
     1459{
     1460  NS_ASSERTION (xcpt, "NULL");
     1461  if (!xcpt)
     1462    return NS_ERROR_INVALID_POINTER;
     1463
     1464  ipcMessageReader reader(data, dataLen);
     1465
     1466  nsresult rv;
     1467  PRUint32 len;
     1468
     1469  void *instance = 0;
     1470  reader.GetBytes(&instance, sizeof(void *));
     1471  if (reader.HasError())
     1472    return NS_ERROR_INVALID_ARG;
     1473
     1474  PtrBits bits = (PtrBits) (instance);
     1475
     1476  if (bits & 0x1)
     1477  {
     1478    // pointer is a peer-side exception instance wrapper,
     1479    // read cahced exception data and create a stub for it.
     1480
     1481    nsCAutoString message;
     1482    len = reader.GetInt32();
     1483    if (len)
     1484    {
     1485      message.SetLength(len);
     1486      char *buf = message.BeginWriting();
     1487      reader.GetBytes(buf, len);
     1488    }
     1489
     1490    nsresult result = reader.GetInt32();
     1491
     1492    nsCAutoString name;
     1493    len = reader.GetInt32();
     1494    if (len)
     1495    {
     1496      name.SetLength(len);
     1497      char *buf = name.BeginWriting();
     1498      reader.GetBytes(buf, len);
     1499    }
     1500
     1501    nsCAutoString filename;
     1502    len = reader.GetInt32();
     1503    if (len)
     1504    {
     1505      filename.SetLength(len);
     1506      char *buf = filename.BeginWriting();
     1507      reader.GetBytes(buf, len);
     1508    }
     1509
     1510    PRUint32 lineNumber = reader.GetInt32();
     1511    PRUint32 columnNumber = reader.GetInt32();
     1512
     1513    if (reader.HasError())
     1514      rv = NS_ERROR_INVALID_ARG;
     1515    else
     1516    {
     1517      DConAddr addr = (DConAddr) (bits & ~0x1);
     1518      nsRefPtr<DConnectStub> stub;
     1519      rv = CreateStub(nsIException::GetIID(), peer, addr,
     1520                      getter_AddRefs(stub));
     1521      if (NS_SUCCEEDED(rv))
     1522      {
     1523        // create a special exception "stub" with cached error info
     1524        ExceptionStub *xcptStub =
     1525          new ExceptionStub (message, result,
     1526                             name, filename,
     1527                             lineNumber, columnNumber,
     1528                             stub);
     1529        if (xcptStub)
     1530        {
     1531          *xcpt = xcptStub;
     1532          NS_ADDREF(xcptStub);
     1533        }
     1534        else
     1535          rv = NS_ERROR_OUT_OF_MEMORY;
     1536      }
     1537    }
     1538  }
     1539  else if (bits)
     1540  {
     1541    // pointer is to our instance wrapper for nsIException we've sent before
     1542    // (the remote method we've called had called us back and got an exception
     1543    // from us that it decided to return as its own result). Replace it with
     1544    // the real instance.
     1545    DConnectInstance *wrapper = (DConnectInstance *) bits;
     1546    if (CheckInstanceAndAddRef(wrapper))
     1547    {
     1548      *xcpt = (nsIException *) wrapper->RealInstance();
     1549      NS_ADDREF(wrapper->RealInstance());
     1550      wrapper->Release();
     1551    }
     1552    else
     1553    {
     1554      NS_NOTREACHED("instance wrapper not found");
     1555      rv = NS_ERROR_INVALID_ARG;
     1556    }
     1557  }
     1558  else
     1559  {
     1560    // the peer explicitly passed us a NULL exception to indicate that the
     1561    // exception on the current thread should be reset
     1562    *xcpt = NULL;
     1563    return NS_OK;
     1564  }
     1565
     1566
     1567  return rv;
     1568}
     1569
     1570//-----------------------------------------------------------------------------
     1571
    11181572DConnectStub::~DConnectStub()
    11191573{
     
    12781732
    12791733  // reset the exception early.  this is necessary because we may return a
    1280   // failure from here without setting an exception (which might be expected by
    1281   // the caller because the interface we are stubbing may indicate in some way
    1282   // that it always sets the exception info on failure).  besides that, resetting
    1283   // the excetion before every IPC call is exactly the same thing as Win32 RPC
    1284   // does, so doing this is useful for getting similarity in behaviors.
     1734  // failure from here without setting an exception (which might be expected
     1735  // by the caller to detect the error origin: the interface we are stubbing
     1736  // may indicate in some way that it always sets the exception info on
     1737  // failure, therefore an "infoless" failure means the origin is RPC).
     1738  // besides that, resetting the excetion before every IPC call is exactly the
     1739  // same thing as Win32 RPC does, so doing this is useful for getting
     1740  // similarity in behaviors.
    12851741
    12861742  nsCOMPtr <nsIExceptionService> es;
     
    13991855  if (NS_FAILED(rv))
    14001856  {
    1401     if (completion.ParamsLen() > 0)
    1402     {
    1403       // we've got an nsIException instance, deserialize it and set in the
    1404       // current thread
    1405       nsresult invoke_rv = rv;
    1406       PtrBits bits = (PtrBits) *((void **) completion.Params());
    1407 
    1408       LOG(("got nsIException instance (%p), will create a stub\n", bits));
    1409 
    1410       NS_ASSERTION(completion.ParamsLen() == sizeof(void*),
    1411                    "wrong nsIException serialization");
    1412 
    1413       if (bits & 0x1)
    1414       {
    1415         DConAddr addr = (DConAddr) (bits & ~0x1);
    1416         nsRefPtr<DConnectStub> stub;
    1417         rv = dConnect->CreateStub(nsIException::GetIID(), mPeerID, addr,
    1418                                   getter_AddRefs(stub));
    1419         if (NS_SUCCEEDED(rv))
    1420         {
    1421           rv = em->SetCurrentException((nsIException *)(nsISupports *) stub);
    1422           // restore the method's result
    1423           rv = invoke_rv;
    1424         }
    1425       }
    1426       else if (bits)
    1427       {
    1428         // pointer is to our instance wrapper for nsIException we've set
    1429         // before (the remote method we've just called had called us back
    1430         // and got an exception from us that it decided to return as its
    1431         // own result). Replace it with the real instance.
    1432         DConnectInstance *wrapper = (DConnectInstance *) bits;
    1433         if (dConnect->CheckInstanceAndAddRef(wrapper))
    1434         {
    1435           rv = em->SetCurrentException((nsIException *) wrapper->RealInstance());
    1436           // restore the method's result
    1437           rv = invoke_rv;
    1438           wrapper->Release();
    1439         }
    1440         else
    1441         {
    1442           NS_NOTREACHED("instance wrapper not found");
    1443           rv = NS_ERROR_INVALID_ARG;
    1444         }
    1445       }
    1446       else
    1447       {
    1448         // reset the exception (as requested by the peer)
    1449         // (it doesn't seem to be really necessary since we always reset it at
    1450         // the beginning, but leave it here for clarity)
    1451         rv = em->SetCurrentException(NULL);
    1452         // restore the method's result
    1453         rv = invoke_rv;
    1454       }
     1857    NS_ASSERTION(completion.ParamsLen() >= sizeof(void*),
     1858                 "invalid nsIException serialization length");
     1859    if (completion.ParamsLen() >= sizeof(void*))
     1860    {
     1861      LOG(("got nsIException instance (%p), will create a stub\n",
     1862           *((void **) completion.Params())));
     1863
     1864      nsIException *xcpt = nsnull;
     1865      rv = dConnect->DeserializeException (completion.Params(),
     1866                                           completion.ParamsLen(),
     1867                                           mPeerID, &xcpt);
     1868      if (NS_SUCCEEDED(rv))
     1869      {
     1870        rv = em->SetCurrentException(xcpt);
     1871        NS_IF_RELEASE(xcpt);
     1872      }
     1873      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception");
    14551874    }
    14561875  }
     
    15461965    }
    15471966
     1967    if (opLen < sizeof(DConnectSetupReply))
     1968    {
     1969      NS_NOTREACHED("unexpected response size");
     1970      mStatus = NS_ERROR_UNEXPECTED;
     1971      return;
     1972    }
     1973
    15481974    const DConnectSetupReply *reply = (const DConnectSetupReply *) op;
    15491975
     
    15541980      mStatus = reply->status;
    15551981
    1556       // we've been sent an nsIException (that can be null) in case of any error,
    1557       // set it in the current thread
    1558       LOG(("got nsIException instance (%p), will create a stub\n", reply->instance));
    1559 
    1560       nsresult rv;
    1561       nsCOMPtr <nsIExceptionService> es;
    1562       es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
    1563       if (NS_SUCCEEDED(rv))
    1564       {
    1565         nsCOMPtr <nsIExceptionManager> em;
    1566         rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
     1982      const PRUint8 *params = ((const PRUint8 *) op) + sizeof (DConnectSetupReply);
     1983      const PRUint32 paramsLen = opLen - sizeof (DConnectSetupReply);
     1984
     1985      NS_ASSERTION(paramsLen >= sizeof(void*),
     1986                   "invalid nsIException serialization length");
     1987      if (paramsLen >= sizeof(void*))
     1988      {
     1989        LOG(("got nsIException instance (%p), will create a stub\n",
     1990             *((void **) params)));
     1991
     1992        nsresult rv;
     1993        nsCOMPtr <nsIExceptionService> es;
     1994        es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
    15671995        if (NS_SUCCEEDED(rv))
    15681996        {
    1569           if (reply->instance)
     1997          nsCOMPtr <nsIExceptionManager> em;
     1998          rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
     1999          if (NS_SUCCEEDED(rv))
    15702000          {
    15712001            // ensure ipcDConnectService is not deleted before we finish
    15722002            nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
    15732003            if (dConnect)
    1574               rv = dConnect->CreateStub(nsIException::GetIID(), sender, reply->instance,
    1575                                         getter_AddRefs(mStub));
     2004            {
     2005              nsIException *xcpt = nsnull;
     2006              rv = dConnect->DeserializeException (params, paramsLen,
     2007                                                   sender, &xcpt);
     2008              if (NS_SUCCEEDED(rv))
     2009              {
     2010                rv = em->SetCurrentException(xcpt);
     2011                NS_IF_RELEASE(xcpt);
     2012              }
     2013            }
    15762014            else
    1577               rv = NS_ERROR_FAILURE;
    1578             if (NS_SUCCEEDED(rv))
    1579             {
    1580               rv = em->SetCurrentException((nsIException *)(nsISupports *) mStub);
    1581             }
    1582           }
    1583           else
    1584           {
    1585             // reset the exception (as requested by the peer)
    1586             rv = em->SetCurrentException(NULL);
     2015              rv = NS_ERROR_UNEXPECTED;
    15872016          }
    15882017        }
    1589       }
    1590 
    1591       if (NS_FAILED(rv))
    1592         mStatus = rv;
     2018        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception");
     2019      }
    15932020    }
    15942021    else
     
    23392766      break;
    23402767  }
     2768
     2769  nsVoidArray wrappers;
    23412770
    23422771  // now, create instance wrapper, and store it in our instances set.
     
    23712800            // reference the newly created wrapper
    23722801            wrapper->AddRef();
     2802
     2803            if (!wrappers.AppendElement(wrapper))
     2804            {
     2805              NS_RELEASE(wrapper);
     2806              rv = NS_ERROR_OUT_OF_MEMORY;
     2807            }
    23732808          }
    23742809        }
     
    23792814    }
    23802815  }
    2381   else
     2816
     2817  NS_IF_RELEASE(instance);
     2818
     2819  ipcMessageWriter writer(64);
     2820
     2821  DConnectSetupReply msg;
     2822  msg.opcode_major = DCON_OP_SETUP_REPLY;
     2823  msg.opcode_minor = 0;
     2824  msg.request_index = setup->request_index;
     2825  msg.instance = wrapper;
     2826  msg.status = rv;
     2827
     2828  writer.PutBytes(&msg, sizeof(msg));
     2829
     2830  if (NS_FAILED(rv))
    23822831  {
    23832832    // try to fetch an nsIException possibly set by one of the setup methods
    23842833    // and send it instead of the failed instance (even if it is null)
    2385     nsresult setup_rv = rv;
    23862834    nsCOMPtr <nsIExceptionService> es;
    23872835    es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
     
    23992847               (nsIException *)exception));
    24002848
    2401           if (exception)
    2402           {
    2403             nsCOMPtr<nsIInterfaceInfo> iinfo;
    2404             rv = GetInterfaceInfo(nsIException::GetIID(), getter_AddRefs(iinfo));
    2405             if (NS_SUCCEEDED(rv))
    2406             {
    2407               nsAutoLock lock (mLock);
    2408 
    2409               // first try to find an existing wrapper for the given object
    2410               if (!FindInstanceAndAddRef(peer, exception,
    2411                                          &nsIException::GetIID(), &wrapper))
    2412               {
    2413                 wrapper = new DConnectInstance(peer, iinfo, exception);
    2414                 if (!wrapper)
    2415                   rv = NS_ERROR_OUT_OF_MEMORY;
    2416                 else
    2417                 {
    2418                   rv = StoreInstance(wrapper);
    2419                   if (NS_FAILED(rv))
    2420                   {
    2421                     delete wrapper;
    2422                     wrapper = nsnull;
    2423                   }
    2424                   else
    2425                   {
    2426                     // reference the newly created wrapper
    2427                     wrapper->AddRef();
    2428                   }
    2429                 }
    2430               }
    2431 
    2432               // wrapper remains referenced when passing it to the client
    2433               // (will be released upon DCON_OP_RELEASE)
    2434             }
    2435           }
    2436           // otherwise, wrapper = nsnull, which will indicate a null nsIException
    2437 
    2438           // restore the setup result
    2439           if (NS_SUCCEEDED(rv))
    2440             rv = setup_rv;
     2849          rv = SerializeException(writer, peer, exception, wrappers);
    24412850        }
    24422851      }
    24432852    }
    2444   }
    2445 
    2446   NS_IF_RELEASE(instance);
    2447 
    2448   DConnectSetupReply msg;
    2449   msg.opcode_major = DCON_OP_SETUP_REPLY;
    2450   msg.opcode_minor = 0;
    2451   msg.request_index = setup->request_index;
    2452   msg.instance = wrapper;
    2453   msg.status = rv;
     2853    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception");
     2854  }
    24542855
    24552856  // fire off SETUP_REPLY, don't wait for a response
    2456   IPC_SendMessage(peer, kDConnectTargetID,
    2457                   (const PRUint8 *) &msg, sizeof(msg));
     2857  if (NS_FAILED(rv))
     2858    rv = IPC_SendMessage(peer, kDConnectTargetID,
     2859                         (const PRUint8 *) &msg, sizeof(msg));
     2860  else
     2861    rv = IPC_SendMessage(peer, kDConnectTargetID,
     2862                         writer.GetBuffer(), writer.GetSize());
     2863
     2864  if (NS_FAILED(rv))
     2865  {
     2866    LOG(("unable to send SETUP_REPLY: rv=%x\n", rv));
     2867    ReleaseWrappers(wrappers);
     2868  }
    24582869}
    24592870
     
    26503061  if (got_exception)
    26513062  {
    2652     // serialize the exception
    2653     rv = SerializeInterfaceParam(writer, peer, nsIException::GetIID(),
    2654                                  exception, wrappers);
     3063    rv = SerializeException(writer, peer, exception, wrappers);
     3064    NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception");
    26553065  }
    26563066  else if (NS_SUCCEEDED(rv) && params)
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h

    r1964 r2093  
    2121 * Contributor(s):
    2222 *   Darin Fisher <[email protected]>
     23 *   Dmitry A. Kuminov <[email protected]>
    2324 *
    2425 * Alternatively, the contents of this file may be used under the terms of
     
    7980};
    8081
    81 #endif
    82 
     82#endif // DCONNECT_MULTITHREADED
     83
     84class nsIException;
    8385class ipcMessageWriter;
    8486
     
    216218                                               nsISupports *obj,
    217219                                               nsVoidArray &wrappers);
     220
     221  NS_HIDDEN_(nsresult) SerializeException(ipcMessageWriter &writer,
     222                                          PRUint32 peer, nsIException *xcpt,
     223                                          nsVoidArray &wrappers);
     224  NS_HIDDEN_(nsresult) DeserializeException(const PRUint8 *data, PRUint32 dataLen,
     225                                            PRUint32 peer, nsIException **xcpt);
    218226
    219227  NS_HIDDEN_(void)     ReleaseWrappers(nsVoidArray &wrappers);
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