summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Ice/Outgoing.cpp63
-rw-r--r--cpp/src/Ice/ProxyFactory.cpp26
2 files changed, 61 insertions, 28 deletions
diff --git a/cpp/src/Ice/Outgoing.cpp b/cpp/src/Ice/Outgoing.cpp
index 4c444b54ed5..bd98109ce16 100644
--- a/cpp/src/Ice/Outgoing.cpp
+++ b/cpp/src/Ice/Outgoing.cpp
@@ -62,40 +62,47 @@ IceInternal::Outgoing::Outgoing(ConnectionI* connection, Reference* ref, const s
}
}
- _reference->getIdentity().__write(&_os);
-
- //
- // For compatibility with the old FacetPath.
- //
- if(_reference->getFacet().empty())
+ try
{
- _os.write(vector<string>());
- }
- else
- {
- vector<string> facetPath;
- facetPath.push_back(_reference->getFacet());
- _os.write(facetPath);
- }
+ _reference->getIdentity().__write(&_os);
- _os.write(operation);
+ //
+ // For compatibility with the old FacetPath.
+ //
+ if(_reference->getFacet().empty())
+ {
+ _os.write(vector<string>());
+ }
+ else
+ {
+ vector<string> facetPath;
+ facetPath.push_back(_reference->getFacet());
+ _os.write(facetPath);
+ }
+
+ _os.write(operation);
- _os.write(static_cast<Byte>(mode));
+ _os.write(static_cast<Byte>(mode));
- _os.writeSize(Int(context.size()));
- Context::const_iterator p;
- for(p = context.begin(); p != context.end(); ++p)
+ _os.writeSize(Int(context.size()));
+ Context::const_iterator p;
+ for(p = context.begin(); p != context.end(); ++p)
+ {
+ _os.write(p->first);
+ _os.write(p->second);
+ }
+
+ //
+ // Input and output parameters are always sent in an
+ // encapsulation, which makes it possible to forward requests as
+ // blobs.
+ //
+ _os.startWriteEncaps();
+ }
+ catch(const LocalException& ex)
{
- _os.write(p->first);
- _os.write(p->second);
+ abort(ex);
}
-
- //
- // Input and output parameters are always sent in an
- // encapsulation, which makes it possible to forward requests as
- // blobs.
- //
- _os.startWriteEncaps();
}
bool
diff --git a/cpp/src/Ice/ProxyFactory.cpp b/cpp/src/Ice/ProxyFactory.cpp
index 31f08404e25..0666f4b2777 100644
--- a/cpp/src/Ice/ProxyFactory.cpp
+++ b/cpp/src/Ice/ProxyFactory.cpp
@@ -109,6 +109,32 @@ IceInternal::ProxyFactory::checkRetryAfterException(const LocalException& ex, co
ex.ice_throw();
}
+ //
+ // There is no point in retrying an operation that resulted in a
+ // MarshalException. This must have been raised locally (because if
+ // it happened in a server it would result in an UnknownLocalException
+ // instead), which means there was a problem in this process that will
+ // not change if we try again.
+ //
+ // The most likely cause for a MarshalException is exceeding the
+ // maximum message size, which is represented by the the subclass
+ // MemoryLimitException. For example, a client can attempt to send a
+ // message that exceeds the maximum memory size, or accumulate enough
+ // batch requests without flushing that the maximum size is reached.
+ //
+ // This latter case is especially problematic, because if we were to
+ // retry a batch request after a MarshalException, we would in fact
+ // silently discard the accumulated requests and allow new batch
+ // requests to accumulate. If the subsequent batched requests do not
+ // exceed the maximum message size, it appears to the client that all
+ // of the batched requests were accepted, when in reality only the
+ // last few are actually sent.
+ //
+ if(dynamic_cast<const MarshalException*>(&ex))
+ {
+ ex.ice_throw();
+ }
+
++cnt;
TraceLevelsPtr traceLevels = _instance->traceLevels();