ioc/dbStatic: dbFreeBase() don't double free alias'd records
dbFreeBase() has been broken since alias() was introduced. Traversal of recList in the function assumed that dbDeleteRecord() remove only the current dbRecordNode. However, dbDeleteRecord() called dbDeleteAliases() which removes alias dbRecordNode s. If this happens (as it often does) to be the node immediately after the real node, dbFreeBase() will then iterate using a ellDelete()d node.
This commit is contained in:
@@ -578,8 +578,6 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||||
dbRecordType *pdbRecordType;
|
||||
dbRecordType *pdbRecordTypeNext;
|
||||
dbFldDes * pdbFldDes;
|
||||
dbRecordNode *pdbRecordNode;
|
||||
dbRecordNode *pdbRecordNodeNext;
|
||||
dbRecordAttribute *pAttribute;
|
||||
dbRecordAttribute *pAttributeNext;
|
||||
devSup *pdevSup;
|
||||
@@ -594,19 +592,21 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||||
brkTable *pbrkTableNext;
|
||||
int i;
|
||||
DBENTRY dbentry;
|
||||
|
||||
long status;
|
||||
|
||||
dbInitEntry(pdbbase,&dbentry);
|
||||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
while(pdbRecordType) {
|
||||
pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
|
||||
while(pdbRecordNode) {
|
||||
pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node);
|
||||
if(!dbFindRecord(&dbentry,pdbRecordNode->recordname))
|
||||
dbDeleteRecord(&dbentry);
|
||||
pdbRecordNode = pdbRecordNodeNext;
|
||||
status = dbFirstRecordType(&dbentry);
|
||||
while(!status) {
|
||||
/* dbDeleteRecord() will remove alias or real record node.
|
||||
* For real record nodes, also removes the nodes of all aliases.
|
||||
* This complicates safe traversal, so we re-start iteration
|
||||
* from the first record after each call.
|
||||
*/
|
||||
while((status = dbFirstRecord(&dbentry))==0) {
|
||||
dbDeleteRecord(&dbentry);
|
||||
}
|
||||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
assert(status==S_dbLib_recNotFound);
|
||||
status = dbNextRecordType(&dbentry);
|
||||
}
|
||||
dbFinishEntry(&dbentry);
|
||||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||||
|
||||
Reference in New Issue
Block a user