Merge remote-tracking branch 'launchpad/3.14'

* launchpad/3.14:
  ioc/dbStatic: dbFreeBase() don't double free alias'd records
  ioc/dbStatic: plug leak in dbFreeBase()
  ioc/dbStatic: whitespace
  Fix indentation warning from GCC
  libCom/test: errlog test more verbose
  libCom: STATIC_ASSERT use c++11 static_assert when possible
  Check for empty PV names in Perl catools

Conflicts:
	src/ioc/dbStatic/dbStaticLib.c
	src/libCom/osi/epicsAssert.h
This commit is contained in:
Michael Davidsaver
2017-05-02 18:31:40 -04:00
8 changed files with 151 additions and 130 deletions

View File

@@ -20,13 +20,16 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "caget.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('caget -h' gives help.)\n"
die "No pv name specified. ('caget.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "caget.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval { CA->pend_io($opt_w); };
if ($@) {

View File

@@ -16,10 +16,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('hw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('cainfo -h' gives help.)\n"
die "No pv name specified. ('cainfo.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "cainfo.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval {
CA->pend_io($opt_w);

View File

@@ -20,14 +20,17 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "camonitor.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('camonitor -h' gives help.)\n"
die "No pv name specified. ('camonitor.pl -h' gives help.)\n"
unless @ARGV;
my %monitors;
my @chans = map { CA->new($_, \&conn_callback); } @ARGV;
my @chans = map { CA->new($_, \&conn_callback); } grep { $_ ne '' } @ARGV;
die "camonitor.pl: Please provide at least one non-empty pv name\n"
unless @chans;
my $fmt = ($opt_F eq ' ') ? "%-30s %s\n" : "%s$opt_F%s\n";

View File

@@ -17,11 +17,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('achlnsStw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('caput -h' gives help.)\n"
die "No pv name specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $pv = shift;
die "caput.pl: Empty pv name given.\n"
unless $pv ne '';
die "No value specified. ('caput -h' gives help.)\n"
die "No value specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $chan = CA->new($pv);

View File

@@ -426,8 +426,6 @@ void dbFreeBase(dbBase *pdbbase)
dbRecordType *pdbRecordType;
dbRecordType *pdbRecordTypeNext;
dbFldDes * pdbFldDes;
dbRecordNode *pdbRecordNode;
dbRecordNode *pdbRecordNodeNext;
dbRecordAttribute *pAttribute;
dbRecordAttribute *pAttributeNext;
devSup *pdevSup;
@@ -446,134 +444,136 @@ void dbFreeBase(dbBase *pdbbase)
dbGuiGroup *pguiGroupNext;
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;
}
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
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);
}
assert(status==S_dbLib_recNotFound);
status = dbNextRecordType(&dbentry);
}
dbFinishEntry(&dbentry);
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
while(pdbRecordType) {
for(i=0; i<pdbRecordType->no_fields; i++) {
pdbFldDes = pdbRecordType->papFldDes[i];
free((void *)pdbFldDes->prompt);
free((void *)pdbFldDes->name);
free((void *)pdbFldDes->extra);
free((void *)pdbFldDes->initial);
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
dbDeviceMenu *pdbDeviceMenu;
for(i=0; i<pdbRecordType->no_fields; i++) {
pdbFldDes = pdbRecordType->papFldDes[i];
free((void *)pdbFldDes->prompt);
free((void *)pdbFldDes->name);
free((void *)pdbFldDes->extra);
free((void *)pdbFldDes->initial);
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
dbDeviceMenu *pdbDeviceMenu;
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
free((void *)pdbDeviceMenu->papChoice);
free((void *)pdbDeviceMenu);
pdbFldDes->ftPvt=0;
}
free((void *)pdbFldDes);
}
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
while(pdevSup) {
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
ellDelete(&pdbRecordType->devList,&pdevSup->node);
free((void *)pdevSup->name);
free((void *)pdevSup->choice);
free((void *)pdevSup);
pdevSup = pdevSupNext;
}
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbRecordType->cdefList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pAttribute =
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
while(pAttribute) {
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
free((void *)pAttribute->name);
free((void *)pAttribute->pdbFldDes);
free(pAttribute);
pAttribute = pAttributeNext;
}
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
free((void *)pdbRecordType->name);
free((void *)pdbRecordType->link_ind);
free((void *)pdbRecordType->papsortFldName);
free((void *)pdbRecordType->sortFldInd);
free((void *)pdbRecordType->papFldDes);
free((void *)pdbRecordType);
pdbRecordType = pdbRecordTypeNext;
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
free((void *)pdbDeviceMenu->papChoice);
free((void *)pdbDeviceMenu);
pdbFldDes->ftPvt=0;
}
free((void *)pdbFldDes);
}
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
while(pdevSup) {
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
ellDelete(&pdbRecordType->devList,&pdevSup->node);
free((void *)pdevSup->name);
free((void *)pdevSup->choice);
free((void *)pdevSup);
pdevSup = pdevSupNext;
}
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbRecordType->cdefList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pAttribute =
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
while(pAttribute) {
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
free((void *)pAttribute->name);
free((void *)pAttribute->pdbFldDes);
free(pAttribute);
pAttribute = pAttributeNext;
}
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
free((void *)pdbRecordType->name);
free((void *)pdbRecordType->link_ind);
free((void *)pdbRecordType->papsortFldName);
free((void *)pdbRecordType->sortFldInd);
free((void *)pdbRecordType->papFldDes);
free((void *)pdbRecordType);
pdbRecordType = pdbRecordTypeNext;
}
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
while(pdbMenu) {
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
ellDelete(&pdbbase->menuList,&pdbMenu->node);
for(i=0; i< pdbMenu->nChoice; i++) {
free((void *)pdbMenu->papChoiceName[i]);
free((void *)pdbMenu->papChoiceValue[i]);
}
free((void *)pdbMenu->papChoiceName);
free((void *)pdbMenu->papChoiceValue);
free((void *)pdbMenu ->name);
free((void *)pdbMenu);
pdbMenu = pdbMenuNext;
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
ellDelete(&pdbbase->menuList,&pdbMenu->node);
for(i=0; i< pdbMenu->nChoice; i++) {
free((void *)pdbMenu->papChoiceName[i]);
free((void *)pdbMenu->papChoiceValue[i]);
}
free((void *)pdbMenu->papChoiceName);
free((void *)pdbMenu->papChoiceValue);
free((void *)pdbMenu ->name);
free((void *)pdbMenu);
pdbMenu = pdbMenuNext;
}
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
while(pdrvSup) {
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
ellDelete(&pdbbase->drvList,&pdrvSup->node);
free((void *)pdrvSup->name);
free((void *)pdrvSup);
pdrvSup = pdrvSupNext;
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
ellDelete(&pdbbase->drvList,&pdrvSup->node);
free((void *)pdrvSup->name);
free((void *)pdrvSup);
pdrvSup = pdrvSupNext;
}
ptext = (dbText *)ellFirst(&pdbbase->registrarList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->registrarList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->registrarList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
ptext = (dbText *)ellFirst(&pdbbase->functionList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->functionList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->functionList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pvar = (dbVariableDef *)ellFirst(&pdbbase->variableList);
while(pvar) {
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
ellDelete(&pdbbase->variableList,&pvar->node);
free((void *)pvar->name);
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
ellDelete(&pdbbase->variableList,&pvar->node);
free((void *)pvar->name);
free((void *)pvar->type);
free((void *)pvar);
pvar = pvarNext;
free((void *)pvar);
pvar = pvarNext;
}
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
while(pbrkTable) {
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,&pbrkTable->node);
free(pbrkTable->name);
free((void *)pbrkTable->paBrkInt);
free((void *)pbrkTable);
pbrkTable = pbrkTableNext;
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,&pbrkTable->node);
free(pbrkTable->name);
free((void *)pbrkTable->paBrkInt);
free((void *)pbrkTable);
pbrkTable = pbrkTableNext;
}
pfilt = (chFilterPlugin *)ellFirst(&pdbbase->filterList);
while(pfilt) {

View File

@@ -44,12 +44,15 @@ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line,
/* Compile-time checks */
#if __cplusplus>=201103L
#define STATIC_ASSERT(expr) static_assert(expr, #expr)
#else
#define STATIC_JOIN(x, y) STATIC_JOIN2(x, y)
#define STATIC_JOIN2(x, y) x ## y
#define STATIC_ASSERT(expr) \
typedef int STATIC_JOIN(static_assert_failed_at_line_, __LINE__) \
[ (expr) ? 1 : -1 ] EPICS_UNUSED
#endif
#ifdef __cplusplus
}

View File

@@ -102,6 +102,12 @@ static const char prefixexpectedmsg[] = "A message without prefix"
static char prefixmsgbuffer[1024];
static
void testEqInt_(int lhs, int rhs, const char *LHS, const char *RHS)
{
testOk(lhs==rhs, "%s (%d) == %s (%d)", LHS, lhs, RHS, rhs);
}
#define testEqInt(L, R) testEqInt_(L, R, #L, #R);
static
void logClient(void* raw, const char* msg)
{
@@ -194,7 +200,7 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 1);
testEqInt(pvt.count, 1);
errlogAddListener(&logClient, &pvt2);
@@ -204,8 +210,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 1);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 1);
/* Removes the first listener */
testOk(1 == errlogRemoveListeners(&logClient, &pvt),
@@ -217,8 +223,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt2.expect);
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 2);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 2);
/* Add the second listener again, then remove both instances */
errlogAddListener(&logClient, &pvt2);
@@ -228,8 +234,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("Something different");
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 2);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 2);
/* Re-add one listener */
errlogAddListener(&logClient, &pvt);
@@ -242,7 +248,7 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", longmsg);
errlogFlush();
testOk1(pvt.count == 3);
testEqInt(pvt.count, 3);
pvt.expect = NULL;
@@ -255,12 +261,12 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", longmsg);
epicsThreadSleep(0.1);
testOk1(pvt.count == 3);
testEqInt(pvt.count, 3);
epicsEventSignal(pvt.jammer);
errlogFlush();
testOk1(pvt.count == 4);
testEqInt(pvt.count, 4);
testDiag("Find buffer capacity (%u theoretical)",LOGBUFSIZE);
@@ -313,7 +319,7 @@ MAIN(epicsErrlogTest)
}
epicsThreadSleep(0.1); /* should really be a second Event */
testOk1(pvt.count == 0);
testEqInt(pvt.count, 0);
/* Extract the first 2 messages, 2*(sizeof(msgNode) + 128) bytes */
pvt.jam = -2;
@@ -321,7 +327,7 @@ MAIN(epicsErrlogTest)
epicsThreadSleep(0.1);
testDiag("Drained %u messages", pvt.count);
testOk1(pvt.count == 2);
testEqInt(pvt.count, 2);
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
errlogPrintfNoConsole("%s", msg); /* Use up that space */
@@ -329,13 +335,13 @@ MAIN(epicsErrlogTest)
testDiag("Overflow the buffer");
errlogPrintfNoConsole("%s", msg);
testOk1(pvt.count == 2);
testEqInt(pvt.count, 2);
epicsEventSignal(pvt.jammer); /* Empty */
errlogFlush();
testDiag("Logged %u messages", pvt.count);
testOk1(pvt.count == N+1);
testEqInt(pvt.count, N+1);
/* Clean up */
testOk(1 == errlogRemoveListeners(&logClient, &pvt),

View File

@@ -169,9 +169,10 @@ static long special(DBADDR *paddr, int after)
subRecord *prec = (subRecord *)paddr->precord;
if (!after) {
if (prec->snam[0] == 0 && prec->pact)
if (prec->snam[0] == 0 && prec->pact) {
prec->pact = FALSE;
prec->rpro = FALSE;
}
return 0;
}