diff --git a/src/ca/cacNotifyIO.cpp b/src/ca/cacNotifyIO.cpp index 3935ad74c..ac3a93122 100644 --- a/src/ca/cacNotifyIO.cpp +++ b/src/ca/cacNotifyIO.cpp @@ -26,7 +26,3 @@ cacNotifyIO::~cacNotifyIO () } } -void cacNotifyIO::destroy () -{ - delete this; -} diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index 3518934ba..5867c0e7a 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -298,7 +298,6 @@ public: bool identifierEquivelence ( unsigned idToMatch ); void * operator new ( size_t size ); void operator delete ( void *pCadaver, size_t size ); - void unistallSubscription ( class netSubscription & ); void resetRetryCount (); unsigned getRetrySeqNo () const; void accessRightsStateChange ( const caar &arIn ); @@ -348,8 +347,9 @@ public: virtual void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count ) = 0; virtual class netSubscription * isSubscription (); virtual void show ( unsigned level ) const; + virtual void uninstall () = 0; ca_uint32_t getID () const; - nciu & channel (); + nciu & channel () const; void destroy (); protected: nciu &chan; @@ -362,15 +362,15 @@ public: void show ( unsigned level ) const; void * operator new ( size_t size ); void operator delete ( void *pCadaver, size_t size ); - void destroy (); - unsigned long getCount (); - unsigned getType (); - unsigned getMask (); + unsigned long getCount () const; + unsigned getType () const; + unsigned getMask () const; private: unsigned long count; unsigned type; unsigned mask; + void uninstall (); void completionNotify (); void completionNotify ( unsigned type, unsigned long count, const void *pData ); void exceptionNotify ( int status, const char *pContext ); @@ -392,11 +392,11 @@ private: unsigned long count; void *pValue; unsigned seqNumber; - void destroy (); void completionNotify (); void completionNotify ( unsigned type, unsigned long count, const void *pData ); void exceptionNotify ( int status, const char *pContext ); void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count ); + void uninstall (); ~netReadCopyIO (); // must be allocated from pool static tsFreeList < class netReadCopyIO, 1024 > freeList; }; @@ -408,7 +408,7 @@ public: void * operator new ( size_t size ); void operator delete ( void *pCadaver, size_t size ); private: - void destroy (); + void uninstall (); void completionNotify (); void completionNotify ( unsigned type, unsigned long count, const void *pData ); void exceptionNotify ( int status, const char *pContext ); @@ -424,7 +424,7 @@ public: void * operator new ( size_t size ); void operator delete ( void *pCadaver, size_t size ); private: - void destroy (); + void uninstall (); void completionNotify (); void completionNotify ( unsigned type, unsigned long count, const void *pData ); void exceptionNotify ( int status, const char *pContext ); @@ -488,19 +488,18 @@ public: void show ( unsigned level ) const; unsigned channelCount () const; void disconnectAllChan ( netiiu & newiiu ); + void destroyAllIO ( nciu &chan ); void connectTimeoutNotify (); bool searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel ); void resetChannelRetryCounts (); void attachChannel ( nciu &chan ); void detachChannel ( nciu &chan ); int installSubscription ( netSubscription &subscr ); - void unistallSubscription ( netSubscription &subscr ); virtual void hostName (char *pBuf, unsigned bufLength) const; virtual const char * pHostName () const; // deprecated - please do not use virtual bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const; virtual bool ca_v42_ok () const; virtual bool ca_v41_ok () const; - virtual bool pushDatagramMsg ( const caHdr &hdr, const void *pExt, ca_uint16_t extsize); virtual int writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue); virtual int writeNotifyRequest ( nciu &, cacNotify &, unsigned type, unsigned nElem, const void *pValue ); @@ -510,6 +509,8 @@ public: virtual void connectAllIO ( nciu &chan ); virtual void disconnectAllIO ( nciu &chan ); virtual int clearChannelRequest ( nciu & ); + virtual void uninstallIO ( baseNMIU & ); + virtual void subscriptionCancelRequest ( netSubscription &subscr, bool userThread ); protected: cac * pCAC () const; @@ -521,7 +522,6 @@ private: virtual void lastChannelDetachNotify (); virtual int subscriptionRequest ( netSubscription &subscr, bool userThread ); - virtual int subscriptionCancelRequest ( netSubscription &subscr, bool userThread ); }; class limboiiu : public netiiu { @@ -831,9 +831,10 @@ private: int status, const char *pContext, unsigned type, unsigned long count ); void connectAllIO ( nciu &chan ); void disconnectAllIO ( nciu &chan ); + void uninstallIO ( baseNMIU & ); int subscriptionRequest ( netSubscription &subscr, bool userThread ); - int subscriptionCancelRequest ( netSubscription &subscr, bool userThread ); + void subscriptionCancelRequest ( netSubscription &subscr, bool userThread ); typedef void ( tcpiiu::*pProtoStubTCP ) (); static const pProtoStubTCP tcpJumpTableCAC []; diff --git a/src/ca/nciu.cpp b/src/ca/nciu.cpp index a74c76446..aa9508703 100644 --- a/src/ca/nciu.cpp +++ b/src/ca/nciu.cpp @@ -67,7 +67,7 @@ void nciu::destroy () { // this occurs here so that it happens when // a lock is not applied - this->piiu->disconnectAllIO ( *this ); + this->piiu->destroyAllIO ( *this ); this->piiu->clearChannelRequest ( *this ); this->cacCtx.destroyNCIU ( *this ); } diff --git a/src/ca/nciu_IL.h b/src/ca/nciu_IL.h index dd48fed93..f2cfba546 100644 --- a/src/ca/nciu_IL.h +++ b/src/ca/nciu_IL.h @@ -127,9 +127,3 @@ inline netiiu * nciu::getPIIU () return this->piiu; } -inline void nciu::unistallSubscription ( netSubscription &subscr ) -{ - this->piiu->unistallSubscription ( subscr ); -} - - diff --git a/src/ca/netReadCopyIO.cpp b/src/ca/netReadCopyIO.cpp index f657234a9..45c5f0f94 100644 --- a/src/ca/netReadCopyIO.cpp +++ b/src/ca/netReadCopyIO.cpp @@ -29,6 +29,11 @@ netReadCopyIO::~netReadCopyIO () } +void netReadCopyIO::uninstall () +{ + this->chan.getPIIU ()->uninstallIO ( *this ); +} + void netReadCopyIO::completionNotify () { this->exceptionNotify ( ECA_INTERNAL, "get completion callback with no data?" ); diff --git a/src/ca/netReadCopyIO_IL.h b/src/ca/netReadCopyIO_IL.h index ce1ba9f5d..5d3a4d03f 100644 --- a/src/ca/netReadCopyIO_IL.h +++ b/src/ca/netReadCopyIO_IL.h @@ -28,5 +28,4 @@ inline void netReadCopyIO::operator delete ( void *pCadaver, size_t size ) netReadCopyIO::freeList.release ( pCadaver, size ); } - #endif // netReadCopyIO_ILh diff --git a/src/ca/netReadNotifyIO.cpp b/src/ca/netReadNotifyIO.cpp index 304833808..f73c45041 100644 --- a/src/ca/netReadNotifyIO.cpp +++ b/src/ca/netReadNotifyIO.cpp @@ -16,18 +16,14 @@ tsFreeList < class netReadNotifyIO, 1024 > netReadNotifyIO::freeList; netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacNotify ¬ifyIn ) : - cacNotifyIO ( notifyIn ), baseNMIU ( chan ) -{ -} + cacNotifyIO ( notifyIn ), baseNMIU ( chan ) {} -netReadNotifyIO::~netReadNotifyIO () -{ - // private NOOP forces pool allocation -} +// private NOOP forces pool allocation +netReadNotifyIO::~netReadNotifyIO () {} -void netReadNotifyIO::destroy () +void netReadNotifyIO::uninstall () { - this->baseNMIU::destroy (); + this->chan.getPIIU ()->uninstallIO ( *this ); } void netReadNotifyIO::completionNotify () diff --git a/src/ca/netSubscription.cpp b/src/ca/netSubscription.cpp index 36b94eaba..734459db1 100644 --- a/src/ca/netSubscription.cpp +++ b/src/ca/netSubscription.cpp @@ -25,12 +25,14 @@ netSubscription::netSubscription ( nciu &chan, unsigned typeIn, unsigned long co netSubscription::~netSubscription () { - this->chan.unistallSubscription ( *this ); + // o netiiu lock must _not_ be applied when calling this + // o uninstall from channel and IIU occur in uninstall method + this->chan.getPIIU ()->subscriptionCancelRequest ( *this, true ); } -void netSubscription::destroy () +void netSubscription::uninstall () { - delete this; + this->chan.getPIIU ()->uninstallIO ( *this ); } class netSubscription * netSubscription::isSubscription () diff --git a/src/ca/netSubscription_IL.h b/src/ca/netSubscription_IL.h index fc01bee23..930f6dd7d 100644 --- a/src/ca/netSubscription_IL.h +++ b/src/ca/netSubscription_IL.h @@ -28,7 +28,7 @@ inline void netSubscription::operator delete ( void *pCadaver, size_t size ) netSubscription::freeList.release ( pCadaver, size ); } -inline unsigned long netSubscription::getCount () +inline unsigned long netSubscription::getCount () const { if ( this->chan.connected () ) { unsigned long nativeCount = chan.nativeElementCount (); @@ -47,12 +47,12 @@ inline unsigned long netSubscription::getCount () } } -inline unsigned netSubscription::getType () +inline unsigned netSubscription::getType () const { return this->type; } -inline unsigned netSubscription::getMask () +inline unsigned netSubscription::getMask () const { return this->mask; } diff --git a/src/ca/netWriteNotifyIO.cpp b/src/ca/netWriteNotifyIO.cpp index cf86e9a29..e8f0dccae 100644 --- a/src/ca/netWriteNotifyIO.cpp +++ b/src/ca/netWriteNotifyIO.cpp @@ -25,9 +25,9 @@ netWriteNotifyIO::~netWriteNotifyIO () // private NOOP forces pool allocation } -void netWriteNotifyIO::destroy () +void netWriteNotifyIO::uninstall () { - this->baseNMIU::destroy (); + this->chan.getPIIU ()->uninstallIO ( *this ); } void netWriteNotifyIO::completionNotify () diff --git a/src/ca/netiiu.cpp b/src/ca/netiiu.cpp index f466db97b..2dcb16b5d 100644 --- a/src/ca/netiiu.cpp +++ b/src/ca/netiiu.cpp @@ -95,6 +95,28 @@ void netiiu::disconnectAllChan ( netiiu & newiiu ) } } +// +// netiiu::destroyAllIO () +// +// care is taken not to not hold the lock while sending event +// subscription delete ( when the IO is deleted ) +// +void netiiu::destroyAllIO ( nciu &chan ) +{ + baseNMIU *pIO; + while ( true ) { + { + epicsAutoMutex autoMutex ( this->mutex ); + pIO = chan.tcpiiuPrivateListOfIO::eventq.first (); + if ( ! pIO ) { + break; + } + pIO->uninstall (); + } + pIO->destroy (); + } +} + void netiiu::connectTimeoutNotify () { epicsAutoMutex autoMutex ( this->mutex ); @@ -133,7 +155,6 @@ bool netiiu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThis status = false; } - return status; } @@ -196,9 +217,8 @@ int netiiu::subscriptionRequest ( netSubscription &subscr, bool ) return ECA_NORMAL; } -int netiiu::subscriptionCancelRequest ( netSubscription &, bool userThread ) +void netiiu::subscriptionCancelRequest ( netSubscription &, bool userThread ) { - return ECA_NORMAL; } int netiiu::installSubscription ( netSubscription &subscr ) @@ -210,19 +230,12 @@ int netiiu::installSubscription ( netSubscription &subscr ) epicsAutoMutex autoMutex ( this->mutex ); subscr.channel ().tcpiiuPrivateListOfIO::eventq.add ( subscr ); } - return this->subscriptionRequest ( subscr, true ); -} - -void netiiu::unistallSubscription ( netSubscription &subscr ) -{ - // we must cancel the subscription first so that clean up - // is guaranteed to occur if a disconnect occurs beteen - // these two steps - this->subscriptionCancelRequest ( subscr, true ); - { + int status = this->subscriptionRequest ( subscr, true ); + if ( status != ECA_NORMAL ) { epicsAutoMutex autoMutex ( this->mutex ); subscr.channel ().tcpiiuPrivateListOfIO::eventq.remove ( subscr ); } + return status; } void netiiu::hostName ( char *pBuf, unsigned bufLength ) const @@ -244,4 +257,10 @@ void netiiu::disconnectAllIO ( nciu & ) void netiiu::connectAllIO ( nciu & ) { +} + +void netiiu::uninstallIO ( baseNMIU &io ) +{ + epicsAutoMutex autoMutex ( this->mutex ); + io.channel ().tcpiiuPrivateListOfIO::eventq.remove ( io ); } \ No newline at end of file diff --git a/src/ca/tcpiiu.cpp b/src/ca/tcpiiu.cpp index 08bd3c350..8acb26075 100644 --- a/src/ca/tcpiiu.cpp +++ b/src/ca/tcpiiu.cpp @@ -1758,7 +1758,7 @@ int tcpiiu::subscriptionRequest ( netSubscription &subscr, bool userThread ) return status; } -int tcpiiu::subscriptionCancelRequest ( netSubscription &subscr, bool userThread ) +void tcpiiu::subscriptionCancelRequest ( netSubscription &subscr, bool userThread ) { if ( this->sendQue.flushThreshold ( 16u ) ) { if ( userThread ) { @@ -1771,29 +1771,17 @@ int tcpiiu::subscriptionCancelRequest ( netSubscription &subscr, bool userThread epicsAutoMutex autoMutex ( this->mutex ); - int status; - baseNMIU *pIO = this->ioTable.remove ( subscr ); - if ( pIO == &subscr ) { - status = this->sendQue.reserveSpace ( 16u ); - if ( status == ECA_NORMAL ) { - if ( ! subscr.channel ().verifyConnected ( *this ) ) { - status = ECA_DISCONNCHID; - } - else { - this->sendQue.pushUInt16 ( CA_PROTO_EVENT_CANCEL ); // cmd - this->sendQue.pushUInt16 ( 0u ); // postsize - this->sendQue.pushUInt16 ( static_cast < ca_uint16_t > ( subscr.getType () ) ); // dataType - this->sendQue.pushUInt16 ( static_cast < ca_uint16_t > ( subscr.getCount () ) ); // count - this->sendQue.pushUInt32 ( subscr.channel ().getSID () ); // cid - this->sendQue.pushUInt32 ( subscr.getID () ); // available - } + int status = this->sendQue.reserveSpace ( 16u ); + if ( status == ECA_NORMAL ) { + if ( subscr.channel ().verifyConnected ( *this ) ) { + this->sendQue.pushUInt16 ( CA_PROTO_EVENT_CANCEL ); // cmd + this->sendQue.pushUInt16 ( 0u ); // postsize + this->sendQue.pushUInt16 ( static_cast < ca_uint16_t > ( subscr.getType () ) ); // dataType + this->sendQue.pushUInt16 ( static_cast < ca_uint16_t > ( subscr.getCount () ) ); // count + this->sendQue.pushUInt32 ( subscr.channel ().getSID () ); // cid + this->sendQue.pushUInt32 ( subscr.getID () ); // available } } - else { - status = ECA_BADMONID; - } - - return status; } void tcpiiu::lastChannelDetachNotify () @@ -1964,22 +1952,22 @@ void tcpiiu::connectAllIO ( nciu &chan ) { epicsAutoMutex autoMutex ( this->mutex ); if ( chan.verifyConnected ( *this ) ) { - tsDLIterBD < baseNMIU > iter = + tsDLIterBD < baseNMIU > pNetIO = chan.tcpiiuPrivateListOfIO::eventq.first (); - while ( iter.valid () ) { - tsDLIterBD < baseNMIU > next = iter.itemAfter (); - class netSubscription *pSubscr = iter->isSubscription (); + while ( pNetIO.valid () ) { + tsDLIterBD < baseNMIU > next = pNetIO.itemAfter (); + class netSubscription *pSubscr = pNetIO->isSubscription (); if ( pSubscr ) { this->subscriptionRequest ( *pSubscr, false ); } else { // it shouldnt be here at this point - so uninstall it - this->ioTable.remove ( *iter ); - chan.tcpiiuPrivateListOfIO::eventq.remove ( *iter ); - iter->exceptionNotify ( ECA_DISCONN, this->pHostName () ); - iter->destroy (); + this->ioTable.remove ( *pNetIO ); + chan.tcpiiuPrivateListOfIO::eventq.remove ( *pNetIO ); + pNetIO->exceptionNotify ( ECA_DISCONN, this->pHostName () ); + pNetIO->destroy (); } - iter = next; + pNetIO = next; } } this->flush (); @@ -1990,24 +1978,33 @@ void tcpiiu::disconnectAllIO ( nciu &chan ) { epicsAutoMutex autoMutex ( this->mutex ); if ( chan.verifyConnected ( *this ) ) { - tsDLIterBD < baseNMIU > iter = + tsDLIterBD < baseNMIU > pNetIO = chan.tcpiiuPrivateListOfIO::eventq.first (); - while ( iter.valid () ) { - tsDLIterBD < baseNMIU > next = iter.itemAfter (); - class netSubscription *pSubscr = iter->isSubscription (); + while ( pNetIO.valid () ) { + tsDLIterBD < baseNMIU > next = pNetIO.itemAfter (); + class netSubscription *pSubscr = pNetIO->isSubscription (); + this->ioTable.remove ( *pNetIO ); if ( pSubscr ) { this->subscriptionCancelRequest ( *pSubscr, false ); } else { // no use after disconnected - so uninstall it - this->ioTable.remove ( *iter ); - chan.tcpiiuPrivateListOfIO::eventq.remove ( *iter ); - iter->exceptionNotify ( ECA_DISCONN, this->pHostName () ); - iter->destroy (); + chan.tcpiiuPrivateListOfIO::eventq.remove ( *pNetIO ); + pNetIO->exceptionNotify ( ECA_DISCONN, this->pHostName () ); + pNetIO->destroy (); } - iter = next; + pNetIO = next; } } } +void tcpiiu::uninstallIO ( baseNMIU &io ) +{ + epicsAutoMutex autoMutex ( this->mutex ); + if ( io.channel ().verifyConnected ( *this ) ) { + this->ioTable.remove ( io ); + } + io.channel ().tcpiiuPrivateListOfIO::eventq.remove ( io ); +} +