diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index dc0fdcdb3..98913581e 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -3,16 +3,28 @@ - EPICS Base R3.14.12.6 Release Notes + EPICS Base R3.14.12.7 Release Notes -

EPICS Base Release 3.14.12.6

+

EPICS Base Release 3.14.12.7

-

Changes between 3.14.12.5 and 3.14.12.6

+

Changes between 3.14.12.6 and 3.14.12.7

+

Checking Periodic Scan Rates

+ +

Code has been added to the IOC startup to better protect it against bad +periodic scan rates, including against locales where . is not +accepted as a decimal separator character. If the scan period in a menuScan +choice string cannot be parsed, the associated periodic scan thread will no +longer be started by the IOC and a warning message will be displayed at iocInit +time. The scanppl command will also flag the faulty menuScan value.

+ + +

Changes between 3.14.12.5 and 3.14.12.6

+

Launchpad Bug-fixes

In addition to the more detailed change descriptions below, the following @@ -277,8 +289,6 @@ it up. This release patches the readline support code to clean up automatically by registering an epicsAtExit() routine.

-

EPICS Base Release 3.14.12.5

-

Changes between 3.14.12.4 and 3.14.12.5

aoRecord raw conversion overflows

diff --git a/src/db/dbScan.c b/src/db/dbScan.c index f764a1760..fb13cb0c3 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -148,8 +148,11 @@ static void scanShutdown(void *arg) interruptAccept = FALSE; for (i = 0; i < nPeriodic; i++) { - papPeriodic[i]->scanCtl = ctlExit; - epicsEventSignal(papPeriodic[i]->loopEvent); + periodic_scan_list *ppsl = papPeriodic[i]; + + if (!ppsl) continue; + ppsl->scanCtl = ctlExit; + epicsEventSignal(ppsl->loopEvent); epicsEventWait(startStopEvent); } @@ -182,16 +185,24 @@ void scanRun(void) interruptAccept = TRUE; scanCtl = ctlRun; - for (i = 0; i < nPeriodic; i++) - papPeriodic[i]->scanCtl = ctlRun; + for (i = 0; i < nPeriodic; i++) { + periodic_scan_list *ppsl = papPeriodic[i]; + + if (!ppsl) continue; + ppsl->scanCtl = ctlRun; + } } void scanPause(void) { int i; - for (i = nPeriodic - 1; i >= 0; --i) - papPeriodic[i]->scanCtl = ctlPause; + for (i = nPeriodic - 1; i >= 0; --i) { + periodic_scan_list *ppsl = papPeriodic[i]; + + if (!ppsl) continue; + ppsl->scanCtl = ctlPause; + } scanCtl = ctlPause; interruptAccept = FALSE; @@ -275,9 +286,11 @@ void scanAdd(struct dbCommon *precord) piosl += prio; /* get piosl for correct priority*/ addToList(precord, &piosl->scan_list); } else if (scan >= SCAN_1ST_PERIODIC) { - addToList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list); + periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC]; + + if (ppsl) + addToList(precord, &ppsl->scan_list); } - return; } void scanDelete(struct dbCommon *precord) @@ -348,28 +361,48 @@ void scanDelete(struct dbCommon *precord) piosl += prio; /*get piosl for correct priority*/ deleteFromList(precord, &piosl->scan_list); } else if (scan >= SCAN_1ST_PERIODIC) { - deleteFromList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list); + periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC]; + + if (ppsl) + deleteFromList(precord, &ppsl->scan_list); } - return; } double scanPeriod(int scan) { + periodic_scan_list *ppsl; + scan -= SCAN_1ST_PERIODIC; if (scan < 0 || scan >= nPeriodic) return 0.0; - return papPeriodic[scan]->period; + ppsl = papPeriodic[scan]; + return ppsl ? ppsl->period : 0.0; } - -int scanppl(double period) /* print periodic list */ + +int scanppl(double period) /* print periodic scan list(s) */ { - periodic_scan_list *ppsl; + dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan"); char message[80]; int i; + if (!pmenu || !papPeriodic) { + printf("scanppl: dbScan subsystem not initialized\n"); + return -1; + } + for (i = 0; i < nPeriodic; i++) { - ppsl = papPeriodic[i]; - if (ppsl == NULL) continue; - if (period > 0.0 && (fabs(period - ppsl->period) >.05)) continue; + periodic_scan_list *ppsl = papPeriodic[i]; + + if (!ppsl) { + const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; + + printf("Periodic scan list for SCAN = '%s' not initialized\n", + choice); + continue; + } + if (period > 0.0 && + (fabs(period - ppsl->period) > 0.05)) + continue; + sprintf(message, "Records with SCAN = '%s' (%lu over-runs):", ppsl->name, ppsl->overruns); printList(&ppsl->scan_list, message); @@ -588,7 +621,7 @@ static void periodicTask(void *arg) if (++overruns >= 10 && epicsTimeDiffInSeconds(&now, &reported) > report_delay) { errlogPrintf("\ndbScan warning from '%s' scan thread:\n" - "\tScan processing averages %.2f seconds (%.2f .. %.2f).\n" + "\tScan processing averages %.3f seconds (%.3f .. %.3f).\n" "\tOver-runs have now happened %u times in a row.\n" "\tTo fix this, move some records to a slower scan rate.\n", ppsl->name, ppsl->period + overtime / overruns, @@ -617,25 +650,30 @@ static void periodicTask(void *arg) static void initPeriodic(void) { - dbMenu *pmenu; - periodic_scan_list *ppsl; + dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan"); int i; - pmenu = dbFindMenu(pdbbase, "menuScan"); if (!pmenu) { - epicsPrintf("initPeriodic: menuScan not present\n"); + errlogPrintf("initPeriodic: menuScan not present\n"); return; } nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC; papPeriodic = dbCalloc(nPeriodic, sizeof(periodic_scan_list*)); periodicTaskId = dbCalloc(nPeriodic, sizeof(void *)); for (i = 0; i < nPeriodic; i++) { - ppsl = dbCalloc(1, sizeof(periodic_scan_list)); + periodic_scan_list *ppsl = dbCalloc(1, sizeof(periodic_scan_list)); + const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; + + if (!epicsScanDouble(choice, &ppsl->period) || + ppsl->period <= 0) { + errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); + free(ppsl); + continue; + } ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); - ppsl->name = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC]; - epicsScanDouble(ppsl->name, &ppsl->period); + ppsl->name = choice; ppsl->scanCtl = ctlPause; ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty); @@ -645,10 +683,11 @@ static void initPeriodic(void) static void spawnPeriodic(int ind) { - periodic_scan_list *ppsl; + periodic_scan_list *ppsl = papPeriodic[ind]; char taskName[20]; - ppsl = papPeriodic[ind]; + if (!ppsl) return; + sprintf(taskName, "scan%g", ppsl->period); periodicTaskId[ind] = epicsThreadCreate( taskName, epicsThreadPriorityScanLow + ind,