summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--cpp/include/Ice/OutgoingAsync.h2
-rw-r--r--cpp/src/Ice/OutgoingAsync.cpp10
-rw-r--r--cpp/test/Ice/ami/AllTests.cpp13
-rw-r--r--cs/src/Ice/OutgoingAsync.cs11
-rw-r--r--java/src/Ice/AsyncResult.java14
-rw-r--r--java/test/Ice/ami/AllTests.java12
-rw-r--r--py/modules/IcePy/Operation.cpp27
-rw-r--r--py/modules/IcePy/Proxy.cpp3
-rw-r--r--py/test/Ice/ami/AllTests.py11
10 files changed, 105 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index e7142622fbe..f0798bf351b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,10 @@ Changes since version 3.4.1
General Changes
===============
+- Added throwLocalException method to the Ice AsyncResult class. If
+ the request fails with a local exception, this method throws the
+ local exception.
+
- Fixed a bug that caused a crash if a timeout occurs while sending
an AMI request and if automatic retry is enabled (the default).
diff --git a/cpp/include/Ice/OutgoingAsync.h b/cpp/include/Ice/OutgoingAsync.h
index 5f65f54a58e..ab062cd7bc2 100644
--- a/cpp/include/Ice/OutgoingAsync.h
+++ b/cpp/include/Ice/OutgoingAsync.h
@@ -65,6 +65,8 @@ public:
bool isSent() const;
void waitForSent();
+ void throwLocalException() const;
+
bool sentSynchronously() const
{
return _sentSynchronously; // No lock needed, immutable once __send() is called
diff --git a/cpp/src/Ice/OutgoingAsync.cpp b/cpp/src/Ice/OutgoingAsync.cpp
index 4698877694b..a598b5b1c31 100644
--- a/cpp/src/Ice/OutgoingAsync.cpp
+++ b/cpp/src/Ice/OutgoingAsync.cpp
@@ -168,6 +168,16 @@ Ice::AsyncResult::waitForSent()
}
}
+void
+Ice::AsyncResult::throwLocalException() const
+{
+ IceUtil::Monitor<IceUtil::Mutex>::Lock sync(_monitor);
+ if(_exception.get())
+ {
+ _exception.get()->ice_throw();
+ }
+}
+
bool
Ice::AsyncResult::__wait()
{
diff --git a/cpp/test/Ice/ami/AllTests.cpp b/cpp/test/Ice/ami/AllTests.cpp
index d5c15332dd3..2b39222dc9a 100644
--- a/cpp/test/Ice/ami/AllTests.cpp
+++ b/cpp/test/Ice/ami/AllTests.cpp
@@ -1975,6 +1975,19 @@ allTests(const Ice::CommunicatorPtr& communicator)
cout << "testing AsyncResult operations... " << flush;
{
+ Test::TestIntfPrx indirect = Test::TestIntfPrx::uncheckedCast(p->ice_adapterId("dummy"));
+ Ice::AsyncResultPtr r;
+ r = indirect->begin_op();
+ try
+ {
+ r->waitForCompleted();
+ r->throwLocalException();
+ test(false);
+ }
+ catch(const Ice::NoEndpointException&)
+ {
+ }
+
testController->holdAdapter();
Ice::AsyncResultPtr r1;
Ice::AsyncResultPtr r2;
diff --git a/cs/src/Ice/OutgoingAsync.cs b/cs/src/Ice/OutgoingAsync.cs
index 4cbd4e17e12..bc78961ac4f 100644
--- a/cs/src/Ice/OutgoingAsync.cs
+++ b/cs/src/Ice/OutgoingAsync.cs
@@ -173,6 +173,17 @@ namespace IceInternal
}
}
+ public void throwLocalException()
+ {
+ lock(monitor_)
+ {
+ if(exception_ != null)
+ {
+ throw exception_;
+ }
+ }
+ }
+
public bool sentSynchronously()
{
return sentSynchronously_; // No lock needed, immutable once send__() is called
diff --git a/java/src/Ice/AsyncResult.java b/java/src/Ice/AsyncResult.java
index 2bf8cddd24a..0ccf2f61aea 100644
--- a/java/src/Ice/AsyncResult.java
+++ b/java/src/Ice/AsyncResult.java
@@ -131,6 +131,20 @@ public class AsyncResult
}
/**
+ * If the invocation failed with a local exception, throws the local exception.
+ **/
+ public final void throwLocalException()
+ {
+ synchronized(_monitor)
+ {
+ if(_exception != null)
+ {
+ throw _exception;
+ }
+ }
+ }
+
+ /**
* This method returns true if a request was written to the client-side
* transport without first being queued. If the request was initially
* queued, this method returns false (independent of whether the request
diff --git a/java/test/Ice/ami/AllTests.java b/java/test/Ice/ami/AllTests.java
index a34331cbc25..2c1b21e98e0 100644
--- a/java/test/Ice/ami/AllTests.java
+++ b/java/test/Ice/ami/AllTests.java
@@ -2086,6 +2086,18 @@ public class AllTests
out.print("testing AsyncResult operations... ");
out.flush();
{
+ TestIntfPrx indirect = TestIntfPrxHelper.uncheckedCast(p.ice_adapterId("dummy"));
+ Ice.AsyncResult r = indirect.begin_op();
+ try
+ {
+ r.waitForCompleted();
+ r.throwLocalException();
+ test(false);
+ }
+ catch(Ice.NoEndpointException ex)
+ {
+ }
+
testController.holdAdapter();
Ice.AsyncResult r1;
Ice.AsyncResult r2;
diff --git a/py/modules/IcePy/Operation.cpp b/py/modules/IcePy/Operation.cpp
index 8c7b4bf33c9..71a081e6e7c 100644
--- a/py/modules/IcePy/Operation.cpp
+++ b/py/modules/IcePy/Operation.cpp
@@ -887,6 +887,31 @@ asyncResultWaitForSent(AsyncResultObject* self)
extern "C"
#endif
static PyObject*
+asyncResultThrowLocalException(AsyncResultObject* self)
+{
+ try
+ {
+ assert(self->result);
+ (*self->result)->throwLocalException();
+ }
+ catch(const Ice::LocalException& ex)
+ {
+ setPythonException(ex);
+ return 0;
+ }
+ catch(...)
+ {
+ assert(false);
+ }
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+#ifdef WIN32
+extern "C"
+#endif
+static PyObject*
asyncResultSentSynchronously(AsyncResultObject* self)
{
bool b = false;
@@ -1121,6 +1146,8 @@ static PyMethodDef AsyncResultMethods[] =
PyDoc_STR(STRCAST("returns true if the request is sent")) },
{ STRCAST("waitForSent"), reinterpret_cast<PyCFunction>(asyncResultWaitForSent), METH_NOARGS,
PyDoc_STR(STRCAST("blocks until the request is sent")) },
+ { STRCAST("throwLocalException"), reinterpret_cast<PyCFunction>(asyncResultThrowLocalException), METH_NOARGS,
+ PyDoc_STR(STRCAST("throw location exception if the request failed with a local exception")) },
{ STRCAST("sentSynchronously"), reinterpret_cast<PyCFunction>(asyncResultSentSynchronously), METH_NOARGS,
PyDoc_STR(STRCAST("returns true if the request was sent synchronously")) },
{ STRCAST("getOperation"), reinterpret_cast<PyCFunction>(asyncResultGetOperation), METH_NOARGS,
diff --git a/py/modules/IcePy/Proxy.cpp b/py/modules/IcePy/Proxy.cpp
index 35c9724e882..c0cdca329ba 100644
--- a/py/modules/IcePy/Proxy.cpp
+++ b/py/modules/IcePy/Proxy.cpp
@@ -1556,12 +1556,11 @@ extern "C"
static PyObject*
proxyIceFlushBatchRequests(ProxyObject* self)
{
- AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations.
-
assert(self->proxy);
try
{
+ AllowThreads allowThreads; // Release Python's global interpreter lock during remote invocations.
(*self->proxy)->ice_flushBatchRequests();
}
catch(const Ice::Exception& ex)
diff --git a/py/test/Ice/ami/AllTests.py b/py/test/Ice/ami/AllTests.py
index 270a4202958..607bc16ba9f 100644
--- a/py/test/Ice/ami/AllTests.py
+++ b/py/test/Ice/ami/AllTests.py
@@ -428,6 +428,7 @@ def allTests(communicator):
r = indirect.begin_op()
try:
indirect.end_op(r)
+ test(False)
except Ice.NoEndpointException:
pass
@@ -827,6 +828,16 @@ def allTests(communicator):
print "ok"
print "testing AsyncResult operations...",
+
+ indirect = Test.TestIntfPrx.uncheckedCast(p.ice_adapterId("dummy"))
+ r = indirect.begin_op()
+ try:
+ r.waitForCompleted()
+ r.throwLocalException()
+ test(False)
+ except Ice.NoEndpointException:
+ pass
+
testController.holdAdapter()
r1 = None
r2 = None