VirtualBox

Ignore:
Timestamp:
Apr 5, 2007 9:02:45 PM (18 years ago)
Author:
vboxsync
Message:

Backed out changeset 20231 because it caused the tests to coredump.

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

    r1958 r1964  
    2121 * Contributor(s):
    2222 *   Darin Fisher <[email protected]>
    23  *   Dmitry A. Kuminov <[email protected]>
    2423 *
    2524 * Alternatively, the contents of this file may be used under the terms of
     
    4645#include "nsIInterfaceInfoManager.h"
    4746#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)
    162160};
    163161
     
    183181{
    184182  nsresult result;
    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)
     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
    188186};
    189187
     
    11181116}
    11191117
    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 }
    1129 static 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 
    1140 class ExceptionStub : public nsIException
    1141 {
    1142 public:
    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 
    1161 private:
    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 
    1172 NS_IMPL_ADDREF(ExceptionStub)
    1173 NS_IMPL_RELEASE(ExceptionStub)
    1174 
    1175 NS_IMETHODIMP
    1176 ExceptionStub::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; */
    1219 NS_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; */
    1228 NS_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; */
    1237 NS_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; */
    1246 NS_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; */
    1255 NS_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; */
    1264 NS_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; */
    1273 NS_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; */
    1281 NS_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; */
    1289 NS_IMETHODIMP ExceptionStub::GetData(nsISupports * *aData)
    1290 {
    1291   if (Exception())
    1292     return Exception()->GetData (aData);
    1293   return NS_ERROR_UNEXPECTED;
    1294 }
    1295 
    1296 /* string toString (); */
    1297 NS_IMETHODIMP ExceptionStub::ToString(char **_retval)
    1298 {
    1299   if (Exception())
    1300     return Exception()->ToString (_retval);
    1301   return NS_ERROR_UNEXPECTED;
    1302 }
    1303 
    1304 nsresult
    1305 ipcDConnectService::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 
    1454 nsresult
    1455 ipcDConnectService::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 
    15721118DConnectStub::~DConnectStub()
    15731119{
     
    17321278
    17331279  // reset the exception early.  this is necessary because we may return a
    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.
     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.
    17411285
    17421286  nsCOMPtr <nsIExceptionService> es;
     
    18551399  if (NS_FAILED(rv))
    18561400  {
    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");
     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      }
    18741455    }
    18751456  }
     
    19651546    }
    19661547
    1967     if (opLen < sizeof(DConnectSetupReply))
    1968     {
    1969       NS_NOTREACHED("unexpected response size");
    1970       mStatus = NS_ERROR_UNEXPECTED;
    1971       return;
    1972     }
    1973 
    19741548    const DConnectSetupReply *reply = (const DConnectSetupReply *) op;
    19751549
     
    19801554      mStatus = reply->status;
    19811555
    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);
     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));
    19951567        if (NS_SUCCEEDED(rv))
    19961568        {
    1997           nsCOMPtr <nsIExceptionManager> em;
    1998           rv = es->GetCurrentExceptionManager (getter_AddRefs(em));
    1999           if (NS_SUCCEEDED(rv))
     1569          if (reply->instance)
    20001570          {
    20011571            // ensure ipcDConnectService is not deleted before we finish
    20021572            nsRefPtr <ipcDConnectService> dConnect (ipcDConnectService::GetInstance());
    20031573            if (dConnect)
     1574              rv = dConnect->CreateStub(nsIException::GetIID(), sender, reply->instance,
     1575                                        getter_AddRefs(mStub));
     1576            else
     1577              rv = NS_ERROR_FAILURE;
     1578            if (NS_SUCCEEDED(rv))
    20041579            {
    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               }
     1580              rv = em->SetCurrentException((nsIException *)(nsISupports *) mStub);
    20131581            }
    2014             else
    2015               rv = NS_ERROR_UNEXPECTED;
     1582          }
     1583          else
     1584          {
     1585            // reset the exception (as requested by the peer)
     1586            rv = em->SetCurrentException(NULL);
    20161587          }
    20171588        }
    2018         NS_ASSERTION(NS_SUCCEEDED(rv), "failed to deserialize/set exception");
    2019       }
     1589      }
     1590
     1591      if (NS_FAILED(rv))
     1592        mStatus = rv;
    20201593    }
    20211594    else
     
    27662339      break;
    27672340  }
    2768 
    2769   nsVoidArray wrappers;
    27702341
    27712342  // now, create instance wrapper, and store it in our instances set.
     
    28002371            // reference the newly created wrapper
    28012372            wrapper->AddRef();
    2802 
    2803             if (!wrappers.AppendElement(wrapper))
     2373          }
     2374        }
     2375      }
     2376
     2377      // wrapper remains referenced when passing it to the client
     2378      // (will be released upon DCON_OP_RELEASE)
     2379    }
     2380  }
     2381  else
     2382  {
     2383    // try to fetch an nsIException possibly set by one of the setup methods
     2384    // and send it instead of the failed instance (even if it is null)
     2385    nsresult setup_rv = rv;
     2386    nsCOMPtr <nsIExceptionService> es;
     2387    es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
     2388    if (NS_SUCCEEDED(rv))
     2389    {
     2390      nsCOMPtr <nsIExceptionManager> em;
     2391      rv = es->GetCurrentExceptionManager (getter_AddRefs (em));
     2392      if (NS_SUCCEEDED(rv))
     2393      {
     2394        nsCOMPtr <nsIException> exception;
     2395        rv = em->GetCurrentException (getter_AddRefs (exception));
     2396        if (NS_SUCCEEDED(rv))
     2397        {
     2398          LOG(("got nsIException instance (%p), will serialize\n",
     2399               (nsIException *)exception));
     2400
     2401          if (exception)
     2402          {
     2403            nsCOMPtr<nsIInterfaceInfo> iinfo;
     2404            rv = GetInterfaceInfo(nsIException::GetIID(), getter_AddRefs(iinfo));
     2405            if (NS_SUCCEEDED(rv))
    28042406            {
    2805               NS_RELEASE(wrapper);
    2806               rv = NS_ERROR_OUT_OF_MEMORY;
     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)
    28072434            }
    28082435          }
     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;
    28092441        }
    28102442      }
    2811 
    2812       // wrapper remains referenced when passing it to the client
    2813       // (will be released upon DCON_OP_RELEASE)
    28142443    }
    28152444  }
    28162445
    28172446  NS_IF_RELEASE(instance);
    2818 
    2819   ipcMessageWriter writer(64);
    28202447
    28212448  DConnectSetupReply msg;
     
    28262453  msg.status = rv;
    28272454
    2828   writer.PutBytes(&msg, sizeof(msg));
    2829 
    2830   if (NS_FAILED(rv))
    2831   {
    2832     // try to fetch an nsIException possibly set by one of the setup methods
    2833     // and send it instead of the failed instance (even if it is null)
    2834     nsCOMPtr <nsIExceptionService> es;
    2835     es = do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID, &rv);
    2836     if (NS_SUCCEEDED(rv))
    2837     {
    2838       nsCOMPtr <nsIExceptionManager> em;
    2839       rv = es->GetCurrentExceptionManager (getter_AddRefs (em));
    2840       if (NS_SUCCEEDED(rv))
    2841       {
    2842         nsCOMPtr <nsIException> exception;
    2843         rv = em->GetCurrentException (getter_AddRefs (exception));
    2844         if (NS_SUCCEEDED(rv))
    2845         {
    2846           LOG(("got nsIException instance (%p), will serialize\n",
    2847                (nsIException *)exception));
    2848 
    2849           rv = SerializeException(writer, peer, exception, wrappers);
    2850         }
    2851       }
    2852     }
    2853     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception");
    2854   }
    2855 
    28562455  // fire off SETUP_REPLY, don't wait for a response
    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   }
     2456  IPC_SendMessage(peer, kDConnectTargetID,
     2457                  (const PRUint8 *) &msg, sizeof(msg));
    28692458}
    28702459
     
    30612650  if (got_exception)
    30622651  {
    3063     rv = SerializeException(writer, peer, exception, wrappers);
    3064     NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get/serialze exception");
     2652    // serialize the exception
     2653    rv = SerializeInterfaceParam(writer, peer, nsIException::GetIID(),
     2654                                 exception, wrappers);
    30652655  }
    30662656  else if (NS_SUCCEEDED(rv) && params)
  • trunk/src/libs/xpcom18a4/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.h

    r1958 r1964  
    2121 * Contributor(s):
    2222 *   Darin Fisher <[email protected]>
    23  *   Dmitry A. Kuminov <[email protected]>
    2423 *
    2524 * Alternatively, the contents of this file may be used under the terms of
     
    8079};
    8180
    82 #endif // DCONNECT_MULTITHREADED
    83 
    84 class nsIException;
     81#endif
     82
    8583class ipcMessageWriter;
    8684
     
    218216                                               nsISupports *obj,
    219217                                               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);
    226218
    227219  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