ca: Fix client bug (race condition) in ipAddrToAsciiEngine
This commit is contained in:
@@ -333,6 +333,12 @@ cac::~cac ()
|
||||
|
||||
this->ipToAEngine.release ();
|
||||
|
||||
// clean-up the list of un-notified msg objects
|
||||
while ( msgForMultiplyDefinedPV * msg = this->msgMultiPVList.get() ) {
|
||||
msg->~msgForMultiplyDefinedPV ();
|
||||
this->mdpvFreeList.release ( msg );
|
||||
}
|
||||
|
||||
errlogFlush ();
|
||||
|
||||
osiSockRelease ();
|
||||
@@ -606,6 +612,8 @@ void cac::transferChanToVirtCircuit (
|
||||
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
|
||||
msgForMultiplyDefinedPV ( this->ipToAEngine,
|
||||
*this, pChan->pName ( guard ), acc );
|
||||
// cac keeps a list of these objects for proper clean-up in ~cac
|
||||
this->msgMultiPVList.add ( *pMsg );
|
||||
// It is possible for the ioInitiate call below to
|
||||
// call the callback directly if queue quota is exceeded.
|
||||
// This callback takes the callback lock and therefore we
|
||||
@@ -1297,6 +1305,8 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->exception ( mgr.cbGuard, guard, ECA_DBLCHNL, buf, __FILE__, __LINE__ );
|
||||
}
|
||||
// remove from the list and delete msg object
|
||||
this->msgMultiPVList.remove ( mfmdpv );
|
||||
mfmdpv.~msgForMultiplyDefinedPV ();
|
||||
this->mdpvFreeList.release ( & mfmdpv );
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ private:
|
||||
resTable < tcpiiu, caServerID > serverTable;
|
||||
tsDLList < tcpiiu > circuitList;
|
||||
tsDLList < SearchDest > searchDestList;
|
||||
tsDLList < msgForMultiplyDefinedPV > msgMultiPVList;
|
||||
tsFreeList
|
||||
< class tcpiiu, 32, epicsMutexNOOP >
|
||||
freeListVirtualCircuit;
|
||||
|
||||
@@ -55,8 +55,10 @@ msgForMultiplyDefinedPV::~msgForMultiplyDefinedPV ()
|
||||
|
||||
void msgForMultiplyDefinedPV::transactionComplete ( const char * pHostNameRej )
|
||||
{
|
||||
// calls into cac for the notification
|
||||
// the msg object (= this) is being deleted as part of the notification
|
||||
this->cb.pvMultiplyDefinedNotify ( *this, this->channel, this->acc, pHostNameRej );
|
||||
// !! dont touch this pointer after this point because object has been deleted !!
|
||||
// !! dont touch 'this' pointer after this point because object has been deleted !!
|
||||
}
|
||||
|
||||
void * msgForMultiplyDefinedPV::operator new ( size_t size,
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "ipAddrToAsciiAsynchronous.h"
|
||||
#include "tsFreeList.h"
|
||||
#include "tsDLList.h"
|
||||
#include "compilerDependencies.h"
|
||||
|
||||
#ifdef msgForMultiplyDefinedPVh_epicsExportSharedSymbols
|
||||
@@ -47,7 +48,9 @@ public:
|
||||
const char * pAcc, const char * pRej ) = 0;
|
||||
};
|
||||
|
||||
class msgForMultiplyDefinedPV : public ipAddrToAsciiCallBack {
|
||||
class msgForMultiplyDefinedPV :
|
||||
public ipAddrToAsciiCallBack,
|
||||
public tsDLNode < msgForMultiplyDefinedPV > {
|
||||
public:
|
||||
msgForMultiplyDefinedPV ( ipAddrToAsciiEngine & engine,
|
||||
callbackForMultiplyDefinedPV &, const char * pChannelName,
|
||||
@@ -62,8 +65,8 @@ private:
|
||||
ipAddrToAsciiTransaction & dnsTransaction;
|
||||
callbackForMultiplyDefinedPV & cb;
|
||||
void transactionComplete ( const char * pHostName );
|
||||
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
|
||||
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
|
||||
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
|
||||
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -265,12 +265,16 @@ void ipAddrToAsciiEnginePrivate::run ()
|
||||
continue;
|
||||
}
|
||||
|
||||
// fix for lp:1580623
|
||||
// a destructing cac sets pCurrent to NULL, so
|
||||
// make local copy to avoid race when releasing the guard
|
||||
ipAddrToAsciiTransactionPrivate *pCur = this->pCurrent;
|
||||
this->callbackInProgress = true;
|
||||
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
// dont call callback with lock applied
|
||||
this->pCurrent->pCB->transactionComplete ( this->nameTmp );
|
||||
pCur->pCB->transactionComplete ( this->nameTmp );
|
||||
}
|
||||
|
||||
this->callbackInProgress = false;
|
||||
|
||||
Reference in New Issue
Block a user