You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by cl...@apache.org on 2014/04/14 16:57:19 UTC
svn commit: r1587222 - in /qpid/trunk/qpid/cpp/src/qpid/sys/windows:
AsynchIO.cpp SslAsynchIO.cpp SslAsynchIO.h
Author: cliffjansen
Date: Mon Apr 14 14:57:19 2014
New Revision: 1587222
URL: http://svn.apache.org/r1587222
Log:
QPID-5669: spurious error on connection close (Windows C++): SSL negotiation failed
Modified:
qpid/trunk/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp
qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp
qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h
Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp?rev=1587222&r1=1587221&r2=1587222&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/AsynchIO.cpp Mon Apr 14 14:57:19 2014
@@ -606,13 +606,25 @@ void AsynchIO::notifyEof(void) {
}
void AsynchIO::notifyDisconnect(void) {
- if (disCallback)
- disCallback(*this);
+ if (disCallback) {
+ DisconnectCallback dcb = disCallback;
+ closedCallback = 0;
+ disCallback = 0;
+ dcb(*this);
+ // May have just been deleted.
+ return;
+ }
}
void AsynchIO::notifyClosed(void) {
- if (closedCallback)
- closedCallback(*this, socket);
+ if (closedCallback) {
+ ClosedCallback ccb = closedCallback;
+ closedCallback = 0;
+ disCallback = 0;
+ ccb(*this, socket);
+ // May have just been deleted.
+ return;
+ }
}
void AsynchIO::notifyBuffersEmpty(void) {
Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp?rev=1587222&r1=1587221&r2=1587222&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.cpp Mon Apr 14 14:57:19 2014
@@ -85,8 +85,10 @@ SslAsynchIO::SslAsynchIO(const qpid::sys
readCallback(rCb),
idleCallback(iCb),
negotiateDoneCallback(nCb),
- callbacksInProgress(0),
queuedDelete(false),
+ queuedClose(false),
+ reapCheckPending(false),
+ started(false),
leftoverPlaintext(0)
{
SecInvalidateHandle(&ctxtHandle);
@@ -105,16 +107,38 @@ SslAsynchIO::~SslAsynchIO() {
}
void SslAsynchIO::queueForDeletion() {
+ // Called exactly once, always on the IO completion thread.
+ bool authenticated = (state != Negotiating);
+ state = ShuttingDown;
+ if (authenticated) {
+ // Tell SChannel we are done.
+ DWORD shutdown = SCHANNEL_SHUTDOWN;
+ SecBuffer shutBuff;
+ shutBuff.cbBuffer = sizeof(DWORD);
+ shutBuff.BufferType = SECBUFFER_TOKEN;
+ shutBuff.pvBuffer = &shutdown;
+ SecBufferDesc desc;
+ desc.ulVersion = SECBUFFER_VERSION;
+ desc.cBuffers = 1;
+ desc.pBuffers = &shutBuff;
+ ::ApplyControlToken(&ctxtHandle, &desc);
+ negotiateStep(0);
+ }
+
+ queueWriteClose();
+ queuedDelete = true;
+
// This method effectively disconnects the layer above; pass it on the
// AsynchIO and delete.
aio->queueForDeletion();
- queuedDelete = true;
- if (!callbacksInProgress)
- delete this;
+
+ if (!reapCheckPending)
+ delete(this);
}
void SslAsynchIO::start(qpid::sys::Poller::shared_ptr poller) {
aio->start(poller);
+ started = true;
startNegotiate();
}
@@ -182,32 +206,23 @@ void SslAsynchIO::notifyPendingWrite() {
}
void SslAsynchIO::queueWriteClose() {
- {
- qpid::sys::Mutex::ScopedLock l(lock);
- if (state == Negotiating) {
- // Never got going, so don't bother trying to close SSL down orderly.
- state = ShuttingDown;
- aio->queueWriteClose();
- return;
- }
- if (state == ShuttingDown)
- return;
- state = ShuttingDown;
- }
-
- DWORD shutdown = SCHANNEL_SHUTDOWN;
- SecBuffer shutBuff;
- shutBuff.cbBuffer = sizeof(DWORD);
- shutBuff.BufferType = SECBUFFER_TOKEN;
- shutBuff.pvBuffer = &shutdown;
- SecBufferDesc desc;
- desc.ulVersion = SECBUFFER_VERSION;
- desc.cBuffers = 1;
- desc.pBuffers = &shutBuff;
- ::ApplyControlToken(&ctxtHandle, &desc);
- negotiateStep(0);
- // When the shutdown sequence is done, negotiateDone() will handle
- // shutting down aio.
+ qpid::sys::Mutex::ScopedLock l(lock);
+ if (queuedClose)
+ return;
+ queuedClose = true;
+ if (started) {
+ reapCheckPending = true;
+ // Move tear down logic to an IO thread.
+ aio->requestCallback(boost::bind(&SslAsynchIO::reapCheck, this));
+ }
+ aio->queueWriteClose();
+}
+
+void SslAsynchIO::reapCheck() {
+ // Serialized check in the IO thread whether to self-delete.
+ reapCheckPending = false;
+ if (queuedDelete)
+ delete(this);
}
bool SslAsynchIO::writeQueueEmpty() {
@@ -259,7 +274,6 @@ void SslAsynchIO::negotiationDone() {
state = Running;
break;
case ShuttingDown:
- aio->queueWriteClose();
break;
default:
assert(0);
@@ -276,6 +290,9 @@ void SslAsynchIO::negotiationFailed(SECU
}
void SslAsynchIO::sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff) {
+ if (state == ShuttingDown) {
+ return;
+ }
if (state != Running) {
negotiateStep(buff);
return;
@@ -398,9 +415,7 @@ void SslAsynchIO::sslDataIn(qpid::sys::A
if (readCallback) {
// The callback guard here is to prevent an upcall from deleting
// this out from under us via queueForDeletion().
- ++callbacksInProgress;
readCallback(*this, temp);
- --callbacksInProgress;
}
else
a.queueReadBuffer(temp); // What else can we do with this???
@@ -410,11 +425,6 @@ void SslAsynchIO::sslDataIn(qpid::sys::A
// go back and handle that.
if (extraBuff != 0)
sslDataIn(a, extraBuff);
-
- // If the upper layer queued for delete, do that now that all the
- // callbacks are done.
- if (queuedDelete && callbacksInProgress == 0)
- delete this;
}
void SslAsynchIO::idle(qpid::sys::AsynchIO&) {
Modified: qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h?rev=1587222&r1=1587221&r2=1587222&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h (original)
+++ qpid/trunk/qpid/cpp/src/qpid/sys/windows/SslAsynchIO.h Mon Apr 14 14:57:19 2014
@@ -93,7 +93,6 @@ protected:
// time to notify the upper layer that the session is up, and also to
// know when it's not legit to pass data through to either side.
enum { Negotiating, Running, Redo, ShuttingDown } state;
- bool sessionUp;
CtxtHandle ctxtHandle;
TimeStamp credExpiry;
@@ -111,13 +110,17 @@ private:
// These are callbacks from AsynchIO to here.
void sslDataIn(qpid::sys::AsynchIO& a, BufferBase *buff);
void idle(qpid::sys::AsynchIO&);
+ void reapCheck();
// These callbacks are to the layer above.
ReadCallback readCallback;
IdleCallback idleCallback;
NegotiateDoneCallback negotiateDoneCallback;
- volatile unsigned int callbacksInProgress; // >0 if w/in callbacks
+
volatile bool queuedDelete;
+ volatile bool queuedClose;
+ volatile bool reapCheckPending;
+ bool started;
// Address of peer, in case it's needed for logging.
std::string peerAddress;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org