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:
@@ -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 ($@) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user