fixed problems where lock was released but channel was

inconsistently attached to an IIU
This commit is contained in:
Jeff Hill
2001-10-04 17:47:07 +00:00
parent e849feeb13
commit 2015e37f53
4 changed files with 63 additions and 67 deletions

View File

@@ -270,17 +270,10 @@ cac::~cac ()
freeListCleanup ( this->tcpLargeRecvBufFreeList );
{
epicsAutoMutex autoMutex ( this->mutex );
epicsAutoMutex autoMutexCB ( this->callbackMutex );
epicsAutoMutex autoMutexCAC ( this->mutex );
if ( this->pudpiiu ) {
tsDLList < nciu > tmpList;
this->pudpiiu->uninstallAllChan ( tmpList );
while ( nciu *pChan = tmpList.get () ) {
this->disconnectAllIO ( *pChan, false );
pChan->disconnect ( limboIIU );
// no need to call disconnect notify or
// access rights notify here
limboIIU.attachChannel ( *pChan );
}
this->removeAllChan ( *this->pudpiiu );
}
}
@@ -301,6 +294,21 @@ cac::~cac ()
this->timerQueue.release ();
}
// must have callback lock and also cac lock
void cac::removeAllChan ( netiiu & srcIIU, netiiu *pDstIIU )
{
// we are protected here because channel delete takes the callback mutex
while ( nciu *pChan = srcIIU.firstChannel() ) {
// if the claim reply has not returned then we will issue
// the clear channel request to the server when the claim reply
// arrives and there is no matching nciu in the client
if ( pChan->connected() ) {
srcIIU.clearChannelRequest ( pChan->getSID(), pChan->getCID() );
}
this->disconnectChannelPrivate ( *pChan, pDstIIU );
}
}
unsigned cac::lowestPriorityLevelAbove ( unsigned priority )
{
unsigned abovePriority;
@@ -857,7 +865,7 @@ void cac::uninstallChannelPrivate ( nciu & chan )
// flush prior to taking the callback lock
this->flushIfRequired ( *chan.getPIIU() );
// if the claim reply has not returned yet then we will issue
// the clear chhannel request to the server when the claim reply
// the clear channel request to the server when the claim reply
// arrives and there is no matching nciu in the client
if ( pChan->connected() ) {
chan.getPIIU()->clearChannelRequest ( chan.getSID(), chan.getCID() );
@@ -1179,27 +1187,26 @@ void cac::connectAllIO ( nciu & chan )
}
// cancel IO operations and monitor subscriptions
// (lock must be applied here)
// -- callback lock and cac lock must be applied here
void cac::disconnectAllIO ( nciu & chan, bool enableCallbacks )
{
tsDLIterBD<baseNMIU> pNetIO = chan.cacPrivateListOfIO::eventq.firstIter();
while ( pNetIO.valid() ) {
tsDLIterBD<baseNMIU> pNext = pNetIO;
pNext++;
bool isSubscr = pNetIO->isSubscription() ? true : false;
if ( ! isSubscr ) {
if ( ! pNetIO->isSubscription() ) {
// no use after disconnected - so uninstall it
this->ioTable.remove ( *pNetIO );
chan.cacPrivateListOfIO::eventq.remove ( *pNetIO );
}
if ( enableCallbacks ) {
epicsAutoMutexRelease unlocker ( this->mutex );
char buf[128];
sprintf ( buf, "host = %100s", chan.pHostName() );
// callbacks are locked at a higher level
sprintf ( buf, "host = %*s",
sizeof(buf)-1, chan.pHostName() );
epicsAutoMutexRelease unlocker ( this->mutex );
pNetIO->exception ( ECA_DISCONN, buf );
}
if ( ! isSubscr ) {
if ( ! pNetIO->isSubscription() ) {
pNetIO->destroy ( *this );
}
pNetIO = pNext;
@@ -1557,29 +1564,36 @@ bool cac::claimCIURespAction ( tcpiiu & iiu,
bool cac::verifyAndDisconnectChan ( tcpiiu & /* iiu */,
const caHdrLargeArray & hdr, void * /* pMsgBdy */ )
{
nciu * pChan;
{
epicsAutoMutex autoMutex ( this->mutex );
pChan = this->chanTable.lookup ( hdr.m_cid );
if ( ! pChan ) {
return true;
}
this->disconnectAllIO ( *pChan, true );
pChan->disconnect ( limboIIU );
{
epicsAutoMutexRelease autoMutexRelease ( this->mutex );
pChan->connectStateNotify ();
pChan->accessRightsNotify ();
}
pChan->disconnect ( *this->pudpiiu );
this->pudpiiu->attachChannel ( *pChan );
this->pSearchTmr->resetPeriod ( 0.0 );
epicsAutoMutex autoMutex ( this->mutex );
nciu * pChan = this->chanTable.lookup ( hdr.m_cid );
if ( ! pChan ) {
return true;
}
assert ( this->pudpiiu );
this->disconnectChannelPrivate ( *pChan, this->pudpiiu );
this->pSearchTmr->resetPeriod ( 0.0 );
return true;
}
// callback lock and cac lock must be applied
void cac::disconnectChannelPrivate ( nciu & chan, netiiu *pDstIIU )
{
this->disconnectAllIO ( chan, true );
chan.getPIIU()->detachChannel ( chan );
chan.disconnect ( limboIIU );
limboIIU.attachChannel ( chan );
if ( pDstIIU ) {
epicsAutoMutexRelease autoMutexRelease ( this->mutex );
chan.connectStateNotify ();
chan.accessRightsNotify ();
}
if ( pDstIIU ) {
limboIIU.detachChannel ( chan );
chan.disconnect ( *pDstIIU );
pDstIIU->attachChannel ( chan );
}
}
bool cac::badTCPRespAction ( tcpiiu & iiu,
const caHdrLargeArray & hdr, void * /* pMsgBdy */ )
{
@@ -1751,7 +1765,8 @@ void cac::notifyDestroyFD ( SOCKET sock ) const
void cac::uninstallIIU ( tcpiiu & iiu )
{
epicsAutoMutex autoMutex ( this->mutex );
epicsAutoMutex autoMutexCB ( this->callbackMutex );
epicsAutoMutex autoMutexCAC ( this->mutex );
if ( iiu.channelCount() ) {
char hostNameTmp[64];
iiu.hostName ( hostNameTmp, sizeof ( hostNameTmp ) );
@@ -1771,19 +1786,7 @@ void cac::uninstallIIU ( tcpiiu & iiu )
this->serverTable.remove ( iiu );
assert ( this->pudpiiu );
tsDLList < nciu > tmpList;
iiu.uninstallAllChan ( tmpList );
while ( nciu *pChan = tmpList.get () ) {
this->disconnectAllIO ( *pChan, true );
pChan->disconnect ( limboIIU );
{
epicsAutoMutexRelease autoMutexRelease ( this->mutex );
pChan->connectStateNotify ();
pChan->accessRightsNotify ();
}
pChan->disconnect ( *this->pudpiiu );
this->pudpiiu->attachChannel ( *pChan );
}
this->removeAllChan ( iiu, this->pudpiiu );
iiu.destroy ();

View File

@@ -206,6 +206,8 @@ private:
void recycleSubscription ( netSubscription &io );
void preemptiveCallbackLock ();
void preemptiveCallbackUnlock ();
void removeAllChan ( netiiu & srcIIU, netiiu * pDstIIU = 0 );
void disconnectChannelPrivate ( nciu & chan, netiiu *pDstIIU );
void ioCompletionNotify ( unsigned id, unsigned type,
arrayElementCount count, const void *pData );

View File

@@ -43,20 +43,6 @@ void netiiu::show ( unsigned level ) const
}
}
// cac lock must also be applied when calling this
void netiiu::uninstallAllChan ( tsDLList < nciu > & dstList )
{
while ( nciu *pChan = this->channelList.get () ) {
// if the claim reply has not returned yet then we will issue
// the clear chhannel request to the server when the claim reply
// arrives and there is no matching nciu in the client
if ( pChan->connected() ) {
this->clearChannelRequest ( pChan->getSID(), pChan->getCID() );
}
dstList.add ( *pChan );
}
}
void netiiu::connectTimeoutNotify ()
{
tsDLIterBD < nciu > chan = this->channelList.firstIter ();

View File

@@ -35,12 +35,12 @@ public:
virtual ~netiiu ();
void show ( unsigned level ) const;
unsigned channelCount () const;
void uninstallAllChan ( tsDLList < nciu > & dstList );
void connectTimeoutNotify ();
bool searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel );
void resetChannelRetryCounts ();
void attachChannel ( nciu &chan );
void detachChannel ( nciu &chan );
nciu * firstChannel ();
int printf ( const char *pformat, ... );
virtual void hostName (char *pBuf, unsigned bufLength) const;
virtual const char * pHostName () const; // deprecated - please do not use
@@ -92,7 +92,7 @@ inline void netiiu::attachChannel ( class nciu &chan )
}
// cac lock must also be applied when calling this
inline void netiiu::detachChannel ( class nciu &chan )
inline void netiiu::detachChannel ( class nciu & chan )
{
this->channelList.remove ( chan );
if ( this->channelList.count () == 0u ) {
@@ -100,4 +100,9 @@ inline void netiiu::detachChannel ( class nciu &chan )
}
}
inline nciu * netiiu::firstChannel ()
{
return this->channelList.first ();
}
#endif // netiiuh