From 51e492fbb184fe92b9d8873cd541b6bc7138f819 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Fri, 9 Feb 2018 14:37:45 +0100
Subject: [PATCH 01/18] Fix numeric events: any number from 0 up to less than
256 is theated as an integer event. Event 0 is no event.
---
src/ioc/db/dbScan.c | 84 +++++++++++++++++++++++++--------------------
src/ioc/db/dbScan.h | 2 +-
2 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index e0c48d4c3..78c098281 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -111,8 +111,8 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
typedef struct event_list {
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
- struct event_list *next;
- char event_name[MAX_STRING_SIZE];
+ struct event_list *next;
+ char eventname[1]; /* actually arbitrary size */
} event_list;
static event_list * volatile pevent_list[256];
static epicsMutexId event_lock;
@@ -249,11 +249,6 @@ void scanAdd(struct dbCommon *precord)
event_list *pel;
eventname = precord->evnt;
- if (strlen(eventname) >= MAX_STRING_SIZE) {
- recGblRecordError(S_db_badField, (void *)precord,
- "scanAdd: too long EVNT value");
- return;
- }
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
@@ -317,24 +312,17 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
- char* eventname;
int prio;
event_list *pel;
scan_list *psl = 0;
- eventname = precord->evnt;
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal PRIO field");
return;
}
- do /* multithreading: make sure pel is consistent */
- pel = pevent_list[0];
- while (pel != pevent_list[0]);
- for (; pel; pel=pel->next) {
- if (strcmp(pel->event_name, eventname) == 0) break;
- }
+ pel = eventNameToHandle(precord->evnt);
if (pel && (psl = &pel->scan_list[prio]))
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
@@ -422,14 +410,12 @@ int scanpel(const char* eventname) /* print event list */
int prio;
event_list *pel;
- do /* multithreading: make sure pel is consistent */
- pel = pevent_list[0];
- while (pel != pevent_list[0]);
- for (; pel; pel = pel->next) {
- if (!eventname || strcmp(pel->event_name, eventname) == 0) {
+ for (pel = pevent_list[0]; pel; pel = pel->next) {
+ if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) {
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) == 0) continue;
- sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
+ sprintf(message, "Event \"%.*s\" Priority %s",
+ sizeof(message)-25, pel->eventname, priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
@@ -480,18 +466,50 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
+ char* p;
+ double eventnumber;
+ size_t namelength;
- if (!eventname || eventname[0] == 0)
- return NULL;
+ if (!eventname) return NULL;
+ while (isblank(eventname[0])) eventname++;
+ if (!eventname[0]) return NULL;
+ namelength = strlen(eventname);
+ while (isblank(eventname[namelength-1])) namelength--;
+
+ /* Backward compatibility with numeric events:
+ Treat any string that represents a double with an
+ integer part between 0 and 255 the same as the integer
+ because it is most probably a conversion from double
+ like from a calc record.
+ */
+ if (epicsParseDouble(eventname, &eventnumber, &p) == 0 &&
+ eventnumber >= 0 && eventnumber < 256 && *p == 0)
+ {
+ if (eventnumber < 1)
+ return NULL; /* 0 is no event */
+ if ((pel = pevent_list[(int)eventnumber]) != NULL)
+ return pel;
+ }
+ else
+ eventnumber = 0; /* not a numeric event */
epicsThreadOnce(&onceId, eventOnce, NULL);
epicsMutexMustLock(event_lock);
for (pel = pevent_list[0]; pel; pel=pel->next) {
- if (strcmp(pel->event_name, eventname) == 0) break;
+ if (strncmp(pel->eventname, eventname, namelength) == 0
+ && pel->eventname[namelength] == 0)
+ break;
}
if (pel == NULL) {
- pel = dbCalloc(1, sizeof(event_list));
- strcpy(pel->event_name, eventname);
+ pel = dbCalloc(1, sizeof(event_list) + namelength);
+ if (eventnumber > 0)
+ {
+ /* backward compatibility: make all numeric events look like integers */
+ sprintf(pel->eventname, "%i", (int)eventnumber);
+ pevent_list[(int)eventnumber] = pel;
+ }
+ else
+ strncpy(pel->eventname, eventname, namelength);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
callbackSetPriority(prio, &pel->callback[prio]);
@@ -501,12 +519,6 @@ event_list *eventNameToHandle(const char *eventname)
}
pel->next=pevent_list[0];
pevent_list[0]=pel;
- { /* backward compatibility */
- char* p;
- long e = strtol(eventname, &p, 0);
- if (*p == 0 && e > 0 && e <= 255)
- pevent_list[e] = pel;
- }
}
epicsMutexUnlock(event_lock);
return pel;
@@ -518,6 +530,7 @@ void postEvent(event_list *pel)
if (scanCtl != ctlRun) return;
if (!pel) return;
+ printf("postEvent %p \"%s\"\n", pel, pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) >0)
callbackRequest(&pel->callback[prio]);
@@ -527,13 +540,8 @@ void postEvent(event_list *pel)
/* backward compatibility */
void post_event(int event)
{
- event_list* pel;
-
if (event <= 0 || event > 255) return;
- do { /* multithreading: make sure pel is consistent */
- pel = pevent_list[event];
- } while (pel != pevent_list[event]);
- postEvent(pel);
+ postEvent(pevent_list[event]);
}
static void ioscanOnce(void *arg)
diff --git a/src/ioc/db/dbScan.h b/src/ioc/db/dbScan.h
index 28d2e133d..d3102712d 100644
--- a/src/ioc/db/dbScan.h
+++ b/src/ioc/db/dbScan.h
@@ -50,7 +50,7 @@ epicsShareFunc void scanCleanup(void);
epicsShareFunc EVENTPVT eventNameToHandle(const char* event);
epicsShareFunc void postEvent(EVENTPVT epvt);
-epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
+epicsShareFunc void post_event(int event);
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);
From 7d836d9554fd728c3dc40915c503a7fa0cf79ab0 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Fri, 9 Feb 2018 16:58:36 +0100
Subject: [PATCH 02/18] some cleanup and scanpel improvement
---
src/ioc/db/dbScan.c | 28 ++++++++++++++++------------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index 78c098281..974cd847f 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -27,6 +27,7 @@
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsInterrupt.h"
+#include "epicsMath.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
#include "epicsRingPointer.h"
@@ -412,10 +413,11 @@ int scanpel(const char* eventname) /* print event list */
for (pel = pevent_list[0]; pel; pel = pel->next) {
if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) {
+ printf("Event \"%s\"\n", pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- if (ellCount(&pel->scan_list[prio].list) == 0) continue;
sprintf(message, "Event \"%.*s\" Priority %s",
- sizeof(message)-25, pel->eventname, priorityName[prio]);
+ (int)(sizeof(message)-25), pel->eventname, priorityName[prio]);
+ sprintf(message, " Priority %s", priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
@@ -466,15 +468,14 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
- char* p;
double eventnumber;
size_t namelength;
if (!eventname) return NULL;
- while (isblank(eventname[0])) eventname++;
+ while (isspace((unsigned char)eventname[0])) eventname++;
if (!eventname[0]) return NULL;
namelength = strlen(eventname);
- while (isblank(eventname[namelength-1])) namelength--;
+ while (isspace((unsigned char)eventname[namelength-1])) namelength--;
/* Backward compatibility with numeric events:
Treat any string that represents a double with an
@@ -482,13 +483,17 @@ event_list *eventNameToHandle(const char *eventname)
because it is most probably a conversion from double
like from a calc record.
*/
- if (epicsParseDouble(eventname, &eventnumber, &p) == 0 &&
- eventnumber >= 0 && eventnumber < 256 && *p == 0)
+ if (epicsParseDouble(eventname, &eventnumber, NULL) == 0)
{
- if (eventnumber < 1)
- return NULL; /* 0 is no event */
- if ((pel = pevent_list[(int)eventnumber]) != NULL)
- return pel;
+ if (!finite(eventnumber))
+ return NULL; /* Inf and NaN are no events */
+ if (eventnumber >= 0 && eventnumber < 256)
+ {
+ if (eventnumber < 1)
+ return NULL; /* 0 is no event */
+ if ((pel = pevent_list[(int)eventnumber]) != NULL)
+ return pel;
+ }
}
else
eventnumber = 0; /* not a numeric event */
@@ -530,7 +535,6 @@ void postEvent(event_list *pel)
if (scanCtl != ctlRun) return;
if (!pel) return;
- printf("postEvent %p \"%s\"\n", pel, pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) >0)
callbackRequest(&pel->callback[prio]);
From adf53756162088892dece1303d604aae748a407c Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Mon, 12 Feb 2018 09:01:05 +0100
Subject: [PATCH 03/18] fix scanpel glob matching
---
src/ioc/db/dbScan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index 974cd847f..a77ec3a5a 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -412,7 +412,7 @@ int scanpel(const char* eventname) /* print event list */
event_list *pel;
for (pel = pevent_list[0]; pel; pel = pel->next) {
- if (!eventname || epicsStrGlobMatch(pel->eventname, eventname) == 0) {
+ if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) {
printf("Event \"%s\"\n", pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
sprintf(message, "Event \"%.*s\" Priority %s",
From d19afc73afd01861c61462d60588595ba9d8673c Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Mon, 12 Feb 2018 12:06:12 +0100
Subject: [PATCH 04/18] Updated RELEASE_NOTES.html with soft event fix.
---
documentation/RELEASE_NOTES.html | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 33f12c441..d8dd5d501 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -29,11 +29,28 @@ be put in a locally created base/configure/CONFIG_SITE.local file instead
of having go modify or replace the original. A new .gitignore pattern
tells git to ignore all configure/*.local files.
+Fix problem with numeric soft events
+Changing from numeric to named soft events introduced an incompatibility
+when a numeric event is converted from a DOUBLE, e.g. from a calc record.
+To make named events backward compatible to numeric events, the logic has
+changed as follows:
+- Leading and trailing spaces are strippd from the event name
+
- Empty event names are no events
+
- If the event name can be converted to double:
+
- If the double is not finite (inf or nan) it is no event.
+
- If the double truncated to integer is between 1 and 255
+ it is a numeric event. Its name is changed to the decimal
+ integer representation.
+
- If the double truncated to integer is 0 it is no event.
+
+ - All other cases are named events
+
+Also scanpel has been modified to accept a glob pattern for
+filtering and to show events with no connected records as well.
Changes from the 3.14 branch since 3.15.5
-
Extend maximum Posix epicsEventWaitWithTimeout() delay
The Posix implementation of epicsEventWaitWithTimeout() was limiting the
From 8a3080c16fd4ac4fdba504ef79d4d275d916aef6 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Tue, 13 Feb 2018 13:50:19 +0100
Subject: [PATCH 05/18] added test for named soft events
---
src/ioc/db/test/Makefile | 13 ++++
src/ioc/db/test/epicsRunDbTests.c | 2 +
src/ioc/db/test/scanEventTest.c | 117 ++++++++++++++++++++++++++++++
src/ioc/db/test/scanEventTest.db | 9 +++
4 files changed, 141 insertions(+)
create mode 100644 src/ioc/db/test/scanEventTest.c
create mode 100644 src/ioc/db/test/scanEventTest.db
diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile
index 215545f4a..ec6b85673 100644
--- a/src/ioc/db/test/Makefile
+++ b/src/ioc/db/test/Makefile
@@ -138,6 +138,19 @@ testHarness_SRCS += dbPutGetTest.db
TESTFILES += ../dbPutGetTest.db
TESTS += testPutGetTest
+TARGETS += $(COMMON_DIR)/scanEventTest.dbd
+DBDDEPENDS_FILES += scanEventTest.dbd$(DEP)
+scanEventTest_DBD += menuGlobal.dbd
+scanEventTest_DBD += menuConvert.dbd
+scanEventTest_DBD += menuScan.dbd
+scanEventTest_DBD += eventRecord.dbd
+scanEventTest_DBD += calcRecord.dbd
+TESTPROD_HOST += scanEventTest
+scanEventTest_SRCS += scanEventTest.c
+scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp
+scanEventTest_LIBS = dbRecStd
+TESTS += scanEventTest
+
# This runs all the test programs in a known working order:
testHarness_SRCS += epicsRunDbTests.c
diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c
index 05fedeb51..ce41815fb 100644
--- a/src/ioc/db/test/epicsRunDbTests.c
+++ b/src/ioc/db/test/epicsRunDbTests.c
@@ -29,6 +29,7 @@ int testDbChannel(void);
int chfPluginTest(void);
int arrShorthandTest(void);
int recGblCheckDeadbandTest(void);
+int scanEventTest(void);
void epicsRunDbTests(void)
{
@@ -47,6 +48,7 @@ void epicsRunDbTests(void)
runTest(arrShorthandTest);
runTest(recGblCheckDeadbandTest);
runTest(chfPluginTest);
+ runTest(scanEventTest);
dbmfFreeChunks();
diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c
new file mode 100644
index 000000000..e48110bcc
--- /dev/null
+++ b/src/ioc/db/test/scanEventTest.c
@@ -0,0 +1,117 @@
+/*************************************************************************\
+* Copyright (c) 2018 Paul Scherrer Institut
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+ \*************************************************************************/
+
+/*
+ * Author: Dirk Zimoch
+ */
+
+#include
+#include "dbStaticLib.h"
+#include "dbAccessDefs.h"
+#include "dbUnitTest.h"
+#include "testMain.h"
+#include "osiFileName.h"
+#include "dbScan.h"
+
+void scanEventTest_registerRecordDeviceDriver(struct dbBase *);
+
+/* test name to event number:
+ num = 0 is no event,
+ num > 0 is numeric event
+ num < 0 is string event (use same unique number for aliases)
+*/
+const struct {char* name; int num;} events[] = {
+ {"", 0},
+ {" ", 0},
+ {"0", 0},
+ {"0.000000", 0},
+ {"-0.00000", 0},
+ {"0.9", 0},
+ {"nan", 0},
+ {"NaN", 0},
+ {"-NAN", 0},
+ {"-inf", 0},
+ {"inf", 0},
+ {"info 1", -1},
+ {" info 1 ", -1},
+ {"-0.9", -2},
+ {"2", 2},
+ {"2.000000", 2},
+ {"2.5", 2},
+ {" 2.5 ", 2},
+ {"+0x02", 2},
+ {"-2", -3},
+ {"-2.000000", -4},
+ {"-2.5", -5},
+ {" -2.5 ", -5},
+};
+
+MAIN(scanEventTest)
+{
+ unsigned int i;
+ int aliases[512] ;
+ int expected_count[512];
+ #define INDX(i) 256-events[i].num
+
+ testPlan(NELEMENTS(events)*2);
+
+ memset(aliases, 0, sizeof(aliases));
+ memset(expected_count, 0, sizeof(expected_count));
+
+ if (dbReadDatabase(&pdbbase, "scanEventTest.dbd",
+ "." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR
+ "../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL))
+ testAbort("Database description 'scanEventTest.dbd' not found");
+
+ scanEventTest_registerRecordDeviceDriver(pdbbase);
+ for (i = 0; i < NELEMENTS(events); i++) {
+ char substitutions[256];
+ sprintf(substitutions, "N=%d,EVENT=%s", i, events[i].name);
+ if (dbReadDatabase(&pdbbase, "scanEventTest.db",
+ "." OSI_PATH_LIST_SEPARATOR "..", substitutions))
+ testAbort("Error reading test database 'scanEventTest.db'");
+ }
+ testIocInitOk();
+ for (i = 0; i < NELEMENTS(events); i++) {
+ EVENTPVT pev = eventNameToHandle(events[i].name);
+ /* test that some names are not events (num=0) */
+ if (events[i].num == 0)
+ testOk(pev == NULL, "\"%s\" -> no event", events[i].name);
+ else
+ {
+ expected_count[INDX(i)]++; /* +1 for postEvent */
+ if (events[i].num > 0)
+ {
+ testOk(pev != NULL, "\"%s\" -> numeric event %d", events[i].name, events[i].num);
+ expected_count[INDX(i)]++; /* +1 for post_event */
+ }
+ else
+ {
+ /* test that some strings resolve the same event (num!=0) */
+ if (!aliases[INDX(i)])
+ {
+ aliases[INDX(i)] = i;
+ testOk(pev != NULL, "\"%s\" -> new named event", events[i].name);
+ }
+ else
+ {
+ testOk(pev == eventNameToHandle(events[aliases[INDX(i)]].name),
+ "\"%s\" alias for \"%s\"", events[i].name, events[aliases[INDX(i)]].name);
+ }
+ }
+ }
+ post_event(events[i].num);
+ postEvent(pev);
+ }
+ for (i = 0; i < NELEMENTS(events); i++) {
+ char pvname[100];
+ sprintf(pvname, "c%d", i);
+ testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]);
+ testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]);
+ }
+
+ return testDone();
+}
diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db
new file mode 100644
index 000000000..439d30da8
--- /dev/null
+++ b/src/ioc/db/test/scanEventTest.db
@@ -0,0 +1,9 @@
+record(calc, "c$(N)") {
+ field(SCAN, "Event")
+ field(EVNT, "$(EVENT)")
+ field(CALC, "VAL+1")
+}
+record(event, "e$(N)") {
+ field(SCAN, "Event")
+ field(VAL, "$(EVENT)")
+}
From 0691fc5f57fb9c6cf79669e3a0d3260c0a1a2f42 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Tue, 13 Feb 2018 14:10:29 +0100
Subject: [PATCH 06/18] fix scanEvent test
---
src/ioc/db/test/scanEventTest.db | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db
index 439d30da8..dbdb61f77 100644
--- a/src/ioc/db/test/scanEventTest.db
+++ b/src/ioc/db/test/scanEventTest.db
@@ -3,7 +3,3 @@ record(calc, "c$(N)") {
field(EVNT, "$(EVENT)")
field(CALC, "VAL+1")
}
-record(event, "e$(N)") {
- field(SCAN, "Event")
- field(VAL, "$(EVENT)")
-}
From 1e9826d1878a2a3cbbed38eea0fd1a1183213917 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Tue, 13 Feb 2018 15:36:21 +0100
Subject: [PATCH 07/18] add tests for calculated numeric soft events
---
src/ioc/db/test/Makefile | 2 ++
src/ioc/db/test/devEventSoft.dbd | 1 +
src/ioc/db/test/scanEventTest.c | 34 +++++++++++++++++++++++++-------
src/ioc/db/test/scanEventTest.db | 11 +++++++++++
4 files changed, 41 insertions(+), 7 deletions(-)
create mode 100644 src/ioc/db/test/devEventSoft.dbd
diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile
index ec6b85673..77e485aec 100644
--- a/src/ioc/db/test/Makefile
+++ b/src/ioc/db/test/Makefile
@@ -144,7 +144,9 @@ scanEventTest_DBD += menuGlobal.dbd
scanEventTest_DBD += menuConvert.dbd
scanEventTest_DBD += menuScan.dbd
scanEventTest_DBD += eventRecord.dbd
+scanEventTest_DBD += devEventSoft.dbd
scanEventTest_DBD += calcRecord.dbd
+scanEventTest_DBD += dfanoutRecord.dbd
TESTPROD_HOST += scanEventTest
scanEventTest_SRCS += scanEventTest.c
scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp
diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd
new file mode 100644
index 000000000..ec3bc2d07
--- /dev/null
+++ b/src/ioc/db/test/devEventSoft.dbd
@@ -0,0 +1 @@
+device(event,CONSTANT,devEventSoft,"Soft Channel")
diff --git a/src/ioc/db/test/scanEventTest.c b/src/ioc/db/test/scanEventTest.c
index e48110bcc..9835b7bf8 100644
--- a/src/ioc/db/test/scanEventTest.c
+++ b/src/ioc/db/test/scanEventTest.c
@@ -35,14 +35,15 @@ const struct {char* name; int num;} events[] = {
{"-NAN", 0},
{"-inf", 0},
{"inf", 0},
- {"info 1", -1},
- {" info 1 ", -1},
- {"-0.9", -2},
{"2", 2},
{"2.000000", 2},
{"2.5", 2},
{" 2.5 ", 2},
{"+0x02", 2},
+ {"3", 3},
+ {"info 1", -1},
+ {" info 1 ", -1},
+ {"-0.9", -2},
{"-2", -3},
{"-2.000000", -4},
{"-2.5", -5},
@@ -51,12 +52,13 @@ const struct {char* name; int num;} events[] = {
MAIN(scanEventTest)
{
- unsigned int i;
+ int i, e;
int aliases[512] ;
int expected_count[512];
#define INDX(i) 256-events[i].num
+ #define MAXEV 5
- testPlan(NELEMENTS(events)*2);
+ testPlan(NELEMENTS(events)*2+(MAXEV+1)*5);
memset(aliases, 0, sizeof(aliases));
memset(expected_count, 0, sizeof(expected_count));
@@ -75,6 +77,7 @@ MAIN(scanEventTest)
testAbort("Error reading test database 'scanEventTest.db'");
}
testIocInitOk();
+ testDiag("Test if eventNameToHandle() strips spaces and handles numeric events");
for (i = 0; i < NELEMENTS(events); i++) {
EVENTPVT pev = eventNameToHandle(events[i].name);
/* test that some names are not events (num=0) */
@@ -103,13 +106,30 @@ MAIN(scanEventTest)
}
}
}
- post_event(events[i].num);
+ post_event(events[i].num); /* triggers numeric events only */
postEvent(pev);
}
+
+ testDiag("Check calculated numeric events (backward compatibility)");
+ for (e = 0; e <= MAXEV; e++) {
+ testdbPutFieldOk("eventnum", DBR_LONG, e);
+ testdbGetFieldEqual("e1", DBR_LONG, e);
+ testdbGetFieldEqual("e2", DBR_LONG, e);
+ testdbPutFieldOk("e3", DBR_LONG, e);
+ testdbPutFieldOk("e3.PROC", DBR_LONG, 1);
+ if (e != 0)
+ for (i = 0; i < NELEMENTS(events); i++)
+ if (events[i].num == e) {
+ expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */
+ break;
+ }
+ }
+
+ testDiag("Check if events have been processed the expected number of times");
for (i = 0; i < NELEMENTS(events); i++) {
char pvname[100];
sprintf(pvname, "c%d", i);
- testDiag("Check if %s (event \"%s\") has processed %d times", pvname, events[i].name, expected_count[INDX(i)]);
+ testDiag("Event \"%s\" expected %d times", events[i].name, expected_count[INDX(i)]);
testdbGetFieldEqual(pvname, DBR_LONG, expected_count[INDX(i)]);
}
diff --git a/src/ioc/db/test/scanEventTest.db b/src/ioc/db/test/scanEventTest.db
index dbdb61f77..9118823d8 100644
--- a/src/ioc/db/test/scanEventTest.db
+++ b/src/ioc/db/test/scanEventTest.db
@@ -3,3 +3,14 @@ record(calc, "c$(N)") {
field(EVNT, "$(EVENT)")
field(CALC, "VAL+1")
}
+record(dfanout, "eventnum") {
+ field(OUTA, "e1 PP")
+ field(FLNK, "e2")
+}
+record(event, "e1") {
+}
+record(event, "e2") {
+ field(INP, "eventnum")
+}
+record(event, "e3") {
+}
From b2d6b67b06bd40acd31bfdbee78d353b98deacfa Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Fri, 16 Feb 2018 11:03:12 +0100
Subject: [PATCH 08/18] removed obsolete code in scanpel
---
src/ioc/db/dbScan.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index a77ec3a5a..cabd73679 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -415,8 +415,7 @@ int scanpel(const char* eventname) /* print event list */
if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) {
printf("Event \"%s\"\n", pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- sprintf(message, "Event \"%.*s\" Priority %s",
- (int)(sizeof(message)-25), pel->eventname, priorityName[prio]);
+ if (ellCount(&pel->scan_list[prio].list) == 0) continue;
sprintf(message, " Priority %s", priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
From 29795656e6be467d541f2292b750129a64f782cf Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Tue, 20 Feb 2018 09:53:06 +0100
Subject: [PATCH 09/18] bugfix for soft events >= 256
---
src/ioc/db/dbScan.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index cabd73679..28c3dda5e 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -467,7 +467,7 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
- double eventnumber;
+ double eventnumber = 0;
size_t namelength;
if (!eventname) return NULL;
@@ -493,9 +493,9 @@ event_list *eventNameToHandle(const char *eventname)
if ((pel = pevent_list[(int)eventnumber]) != NULL)
return pel;
}
+ else
+ eventnumber = 0; /* not a numeric event between 1 and 255 */
}
- else
- eventnumber = 0; /* not a numeric event */
epicsThreadOnce(&onceId, eventOnce, NULL);
epicsMutexMustLock(event_lock);
From 428a8f57e9a5caf8949702daf401cdd0832e5dd1 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Tue, 20 Feb 2018 10:20:37 -0600
Subject: [PATCH 10/18] Fix typos in Channel Filters doc
---
src/std/filters/filters.dbd.pod | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/std/filters/filters.dbd.pod b/src/std/filters/filters.dbd.pod
index db97907a5..f1a848469 100644
--- a/src/std/filters/filters.dbd.pod
+++ b/src/std/filters/filters.dbd.pod
@@ -146,9 +146,9 @@ Note: Negative index numbers address from the end of the array, with C<-1> being
=item Square bracket notation C<[start:increment:end]> (shorthand)
-The common square bracket notation with can be used in place of JSON.
+The common square bracket notation which can be used in place of JSON.
Any parameter may be omitted (keeping the colons) to use the default value.
-If only one colon is included, this means C<[start:end]> with a increment of 1.
+If only one colon is included, this means C<[start:end]> with an increment of 1.
If only a single parameter is used C<[index]> the filter returns one element.
=item Start index C<"s">
From e50c46851274f4f4cf791428a5c2bab9f1f4c677 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Mon, 26 Feb 2018 11:41:20 +0100
Subject: [PATCH 11/18] moved scanEventTest from src/ioc/db/test to
src/std/rec/test
---
src/ioc/db/test/Makefile | 15 ---------------
src/ioc/db/test/devEventSoft.dbd | 1 -
src/ioc/db/test/epicsRunDbTests.c | 2 --
src/std/rec/test/Makefile | 9 +++++++++
src/std/rec/test/epicsRunRecordTests.c | 2 ++
src/{ioc/db => std/rec}/test/scanEventTest.c | 0
src/{ioc/db => std/rec}/test/scanEventTest.db | 0
7 files changed, 11 insertions(+), 18 deletions(-)
delete mode 100644 src/ioc/db/test/devEventSoft.dbd
rename src/{ioc/db => std/rec}/test/scanEventTest.c (100%)
rename src/{ioc/db => std/rec}/test/scanEventTest.db (100%)
diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile
index 77e485aec..215545f4a 100644
--- a/src/ioc/db/test/Makefile
+++ b/src/ioc/db/test/Makefile
@@ -138,21 +138,6 @@ testHarness_SRCS += dbPutGetTest.db
TESTFILES += ../dbPutGetTest.db
TESTS += testPutGetTest
-TARGETS += $(COMMON_DIR)/scanEventTest.dbd
-DBDDEPENDS_FILES += scanEventTest.dbd$(DEP)
-scanEventTest_DBD += menuGlobal.dbd
-scanEventTest_DBD += menuConvert.dbd
-scanEventTest_DBD += menuScan.dbd
-scanEventTest_DBD += eventRecord.dbd
-scanEventTest_DBD += devEventSoft.dbd
-scanEventTest_DBD += calcRecord.dbd
-scanEventTest_DBD += dfanoutRecord.dbd
-TESTPROD_HOST += scanEventTest
-scanEventTest_SRCS += scanEventTest.c
-scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp
-scanEventTest_LIBS = dbRecStd
-TESTS += scanEventTest
-
# This runs all the test programs in a known working order:
testHarness_SRCS += epicsRunDbTests.c
diff --git a/src/ioc/db/test/devEventSoft.dbd b/src/ioc/db/test/devEventSoft.dbd
deleted file mode 100644
index ec3bc2d07..000000000
--- a/src/ioc/db/test/devEventSoft.dbd
+++ /dev/null
@@ -1 +0,0 @@
-device(event,CONSTANT,devEventSoft,"Soft Channel")
diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c
index ce41815fb..05fedeb51 100644
--- a/src/ioc/db/test/epicsRunDbTests.c
+++ b/src/ioc/db/test/epicsRunDbTests.c
@@ -29,7 +29,6 @@ int testDbChannel(void);
int chfPluginTest(void);
int arrShorthandTest(void);
int recGblCheckDeadbandTest(void);
-int scanEventTest(void);
void epicsRunDbTests(void)
{
@@ -48,7 +47,6 @@ void epicsRunDbTests(void)
runTest(arrShorthandTest);
runTest(recGblCheckDeadbandTest);
runTest(chfPluginTest);
- runTest(scanEventTest);
dbmfFreeChunks();
diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile
index 5322c8e92..70b6e173e 100644
--- a/src/std/rec/test/Makefile
+++ b/src/std/rec/test/Makefile
@@ -37,6 +37,15 @@ testHarness_SRCS += analogMonitorTest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/analogMonitorTest.dbd ../analogMonitorTest.db
TESTS += analogMonitorTest
+TARGETS += $(COMMON_DIR)/scanEventTest.dbd
+DBDDEPENDS_FILES += scanEventTest.dbd$(DEP)
+scanEventTest_DBD += base.dbd
+TESTPROD_HOST += scanEventTest
+scanEventTest_SRCS += scanEventTest.c
+scanEventTest_SRCS += scanEventTest_registerRecordDeviceDriver.cpp
+TESTFILES += $(COMMON_DIR)/scanEventTest.dbd ../scanEventTest.db
+TESTS += scanEventTest
+
TARGETS += $(COMMON_DIR)/regressTest.dbd
DBDDEPENDS_FILES += regressTest.dbd$(DEP)
regressTest_DBD += base.dbd
diff --git a/src/std/rec/test/epicsRunRecordTests.c b/src/std/rec/test/epicsRunRecordTests.c
index 092c0a6ce..1a7133c19 100644
--- a/src/std/rec/test/epicsRunRecordTests.c
+++ b/src/std/rec/test/epicsRunRecordTests.c
@@ -14,6 +14,7 @@
int analogMonitorTest(void);
int arrayOpTest(void);
+int scanEventTest(void);
void epicsRunRecordTests(void)
{
@@ -22,6 +23,7 @@ void epicsRunRecordTests(void)
runTest(analogMonitorTest);
runTest(arrayOpTest);
+ runTest(scanEventTest);
epicsExit(0); /* Trigger test harness */
}
diff --git a/src/ioc/db/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c
similarity index 100%
rename from src/ioc/db/test/scanEventTest.c
rename to src/std/rec/test/scanEventTest.c
diff --git a/src/ioc/db/test/scanEventTest.db b/src/std/rec/test/scanEventTest.db
similarity index 100%
rename from src/ioc/db/test/scanEventTest.db
rename to src/std/rec/test/scanEventTest.db
From 396cf4ee3f7194b6e4939fba7708d2b87e0740aa Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Wed, 7 Mar 2018 14:49:12 +0100
Subject: [PATCH 12/18] remove special handling for inf and nan events
---
src/ioc/db/dbScan.c | 5 +----
src/std/rec/test/scanEventTest.c | 29 +++++++++++++++++------------
2 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c
index 28c3dda5e..e9dc178a2 100644
--- a/src/ioc/db/dbScan.c
+++ b/src/ioc/db/dbScan.c
@@ -27,7 +27,6 @@
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsInterrupt.h"
-#include "epicsMath.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
#include "epicsRingPointer.h"
@@ -484,8 +483,6 @@ event_list *eventNameToHandle(const char *eventname)
*/
if (epicsParseDouble(eventname, &eventnumber, NULL) == 0)
{
- if (!finite(eventnumber))
- return NULL; /* Inf and NaN are no events */
if (eventnumber >= 0 && eventnumber < 256)
{
if (eventnumber < 1)
@@ -493,7 +490,7 @@ event_list *eventNameToHandle(const char *eventname)
if ((pel = pevent_list[(int)eventnumber]) != NULL)
return pel;
}
- else
+ else
eventnumber = 0; /* not a numeric event between 1 and 255 */
}
diff --git a/src/std/rec/test/scanEventTest.c b/src/std/rec/test/scanEventTest.c
index 9835b7bf8..595264a8f 100644
--- a/src/std/rec/test/scanEventTest.c
+++ b/src/std/rec/test/scanEventTest.c
@@ -14,6 +14,7 @@
#include "dbUnitTest.h"
#include "testMain.h"
#include "osiFileName.h"
+#include "epicsThread.h"
#include "dbScan.h"
void scanEventTest_registerRecordDeviceDriver(struct dbBase *);
@@ -24,23 +25,22 @@ void scanEventTest_registerRecordDeviceDriver(struct dbBase *);
num < 0 is string event (use same unique number for aliases)
*/
const struct {char* name; int num;} events[] = {
+/* No events */
+ {NULL, 0},
{"", 0},
{" ", 0},
{"0", 0},
{"0.000000", 0},
{"-0.00000", 0},
{"0.9", 0},
- {"nan", 0},
- {"NaN", 0},
- {"-NAN", 0},
- {"-inf", 0},
- {"inf", 0},
+/* Numeric events */
{"2", 2},
{"2.000000", 2},
{"2.5", 2},
{" 2.5 ", 2},
{"+0x02", 2},
{"3", 3},
+/* Named events */
{"info 1", -1},
{" info 1 ", -1},
{"-0.9", -2},
@@ -48,6 +48,11 @@ const struct {char* name; int num;} events[] = {
{"-2.000000", -4},
{"-2.5", -5},
{" -2.5 ", -5},
+ {"nan", -6},
+ {"NaN", -7},
+ {"-NAN", -8},
+ {"-inf", -9},
+ {"inf", -10},
};
MAIN(scanEventTest)
@@ -117,14 +122,14 @@ MAIN(scanEventTest)
testdbGetFieldEqual("e2", DBR_LONG, e);
testdbPutFieldOk("e3", DBR_LONG, e);
testdbPutFieldOk("e3.PROC", DBR_LONG, 1);
- if (e != 0)
- for (i = 0; i < NELEMENTS(events); i++)
- if (events[i].num == e) {
- expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */
- break;
- }
+ for (i = 0; i < NELEMENTS(events); i++)
+ if (e > 0 && e < 256 && events[i].num == e) { /* numeric events */
+ expected_count[INDX(i)]+=3; /* +1 for eventnum->e1, +1 for e2<-eventnum, +1 for e3 */
+ break;
+ }
}
-
+ /* Allow records to finish processing */
+ epicsThreadSleep(0.1);
testDiag("Check if events have been processed the expected number of times");
for (i = 0; i < NELEMENTS(events); i++) {
char pvname[100];
From 2b4a9632b7e21a60b80e1454e44db41d8128ad06 Mon Sep 17 00:00:00 2001
From: Dirk Zimoch
Date: Wed, 7 Mar 2018 14:51:38 +0100
Subject: [PATCH 13/18] update RELEASE_NOTES for named event fix
---
documentation/RELEASE_NOTES.html | 27 +++++++++------------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index d8dd5d501..d19664ea1 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,6 +16,14 @@
+Fix problem with numeric soft events
+Changing from numeric to named soft events introduced an incompatibility
+when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record.
+The post_event() API is not marked deprecated any more.
+
+
Also scanpel has been modified to accept a glob pattern for
+event name filtering and to show events with no connected records as well.
+
Add osiSockOptMcastLoop_t and osiSockTest
Added a new OS-independent typedef for multicast socket options, and a test
@@ -29,28 +37,11 @@ be put in a locally created base/configure/CONFIG_SITE.local file instead
of having go modify or replace the original. A new .gitignore pattern
tells git to ignore all configure/*.local files.
-Fix problem with numeric soft events
-Changing from numeric to named soft events introduced an incompatibility
-when a numeric event is converted from a DOUBLE, e.g. from a calc record.
-To make named events backward compatible to numeric events, the logic has
-changed as follows:
-- Leading and trailing spaces are strippd from the event name
-
- Empty event names are no events
-
- If the event name can be converted to double:
-
- If the double is not finite (inf or nan) it is no event.
-
- If the double truncated to integer is between 1 and 255
- it is a numeric event. Its name is changed to the decimal
- integer representation.
-
- If the double truncated to integer is 0 it is no event.
-
- - All other cases are named events
-
-Also scanpel has been modified to accept a glob pattern for
-filtering and to show events with no connected records as well.
Changes from the 3.14 branch since 3.15.5
+
Extend maximum Posix epicsEventWaitWithTimeout() delay
The Posix implementation of epicsEventWaitWithTimeout() was limiting the
From 05a3699b49642d43655022f365b7bb8c7ed4460b Mon Sep 17 00:00:00 2001
From: Bruce Hill
Date: Sat, 18 Feb 2017 03:27:49 -0800
Subject: [PATCH 14/18] Update pcas CA error msgs to include the pv name for
easier debugging.
---
src/ca/legacy/pcas/generic/casPVI.cc | 32 ++++++++++++++++------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/src/ca/legacy/pcas/generic/casPVI.cc b/src/ca/legacy/pcas/generic/casPVI.cc
index 50e5d27a7..48692b99b 100644
--- a/src/ca/legacy/pcas/generic/casPVI.cc
+++ b/src/ca/legacy/pcas/generic/casPVI.cc
@@ -26,6 +26,11 @@
#include "casAsyncIOI.h"
#include "casMonitor.h"
+
+// Use casErrMessage instead of errMessage to show PV name
+#define casErrMessage(S, PM) \
+ errPrintf(S, __FILE__, __LINE__, ", %s, %s", getName(), PM)
+
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
nIOAttached ( 0u ), deletePending ( false ) {}
@@ -146,7 +151,7 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
// gddArray(int app, aitEnum prim, int dimen, ...);
gdd * pTmp = new gddScalar ( gddAppType_enums );
if ( pTmp == NULL ) {
- errMessage ( S_cas_noMemory,
+ casErrMessage ( S_cas_noMemory,
"unable to create gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
return S_cas_noMemory;
@@ -156,8 +161,8 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
gddAppType_enums, MAX_ENUM_STATES );
if ( status != S_cas_success ) {
pTmp->unreference ();
- errMessage ( status,
- "unable to to config gdd for read of application type \"enums\" string"
+ casErrMessage ( status,
+ "unable to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV");
return status;
}
@@ -187,9 +192,9 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
epicsGuard < epicsMutex > guard ( this->mutex );
if ( resp.isContainer() ) {
- errMessage ( S_cas_badType,
- "application type \"enums\" string conversion table for"
- " enumerated PV was a container (expected vector of strings)" );
+ casErrMessage ( S_cas_badType,
+ "Invalid \"enums\" string conversion table for"
+ " enumerated PV (container instead of vector of strings)" );
return;
}
@@ -197,14 +202,14 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
if ( resp.primitiveType() == aitEnumString ) {
aitString *pStr = (aitString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->string() ) ) {
- errMessage ( S_cas_noMemory,
+ casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else if ( resp.primitiveType() == aitEnumFixedString ) {
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->fixed_string ) ) {
- errMessage ( S_cas_noMemory,
+ casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
@@ -232,7 +237,7 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitString *pStr = (aitString *) resp.dataVoid ();
for ( index = 0; indexenumStrTbl.setString ( index, pStr[index].string() ) ) {
- errMessage ( S_cas_noMemory,
+ casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
@@ -241,19 +246,18 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
for ( index = 0; index < count; index++ ) {
if ( ! this->enumStrTbl.setString ( index, pStr[index].fixed_string ) ) {
- errMessage ( S_cas_noMemory,
+ casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
}
else {
- errMessage ( S_cas_badType,
- "application type \"enums\" string conversion"
- " table for enumerated PV isnt a string type?" );
+ casErrMessage( S_cas_badType,
+ "bad \"enums\" string conversion table for enumerated PV" );
}
}
else {
- errMessage ( S_cas_badType,
+ casErrMessage ( S_cas_badType,
"application type \"enums\" string conversion table"
" for enumerated PV was multi-dimensional"
" (expected vector of strings)" );
From b9443f8813e29a764b517e1f5f329ae952c9cd07 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 23 Mar 2018 11:39:53 -0500
Subject: [PATCH 15/18] Tell MSVC to use absolute filenames in diagnostics (-FC
flag)
---
configure/os/CONFIG.win32-x86.win32-x86 | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86
index f5b21cc2e..54a0ec954 100644
--- a/configure/os/CONFIG.win32-x86.win32-x86
+++ b/configure/os/CONFIG.win32-x86.win32-x86
@@ -85,16 +85,20 @@ CPP = cl -nologo -C -E
# Configure OS vendor C++ compiler
#
-# __STDC__=0 gives us both:
-# 1) define STDC for code (pretend ANSI conformance)
-# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
-# because MS uses: if __STDC__ ... disable many nice things
-#
# -EHsc - generate code for exceptions
# -GR - generate code for run time type identification
#
CCC = cl -EHsc -GR
-CODE_CPPFLAGS += -nologo -D__STDC__=0
+
+# Other compiler flags, used for CPP, C and C++
+#
+# -FC - Show absolute path of source file in diagnostics
+# -D__STDC__=0 gives us both:
+# 1) define STDC for code (pretend ANSI conformance)
+# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
+# because MS uses: if __STDC__ ... disable many nice things
+#
+CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
From 91ce807e8beedc3d6449cee4209ae1b14d4d0be1 Mon Sep 17 00:00:00 2001
From: Benjamin Franksen
Date: Wed, 11 Apr 2018 12:58:28 +0200
Subject: [PATCH 16/18] Fix for lp: #1751380
Add warnings about possible deadlock to the docs for ca_clear_channel,
ca_clear_subscription, and ca_context_destroy.
---
src/ca/CAref.html | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/ca/CAref.html b/src/ca/CAref.html
index 13bcd795f..0651b2c26 100644
--- a/src/ca/CAref.html
+++ b/src/ca/CAref.html
@@ -2674,6 +2674,14 @@ automatically released by the system when the process exits and
vxWorks or RTEMS no cleanup occurs unless the application calls
ca_context_destroy().
+Note: This operation blocks until any user callbacks for any channel
+created in the current context have run to completion. If callbacks take a
+lock (mutex) then it is the user's responsibility to ensure that this lock
+is not held when ca_clear_context() is called, otherwise a
+deadlock may ensue. (See also ca_clear_channel() and ca_clear_subscription().)
+
Returns
ECA_NORMAL - Normal successful completion
@@ -2819,6 +2827,12 @@ efficiently sent over the network in one message.
clearing a channel does shutdown and reclaim any channel state change event
subscriptions (monitors) registered with the channel.
+Note: This operation blocks until any user callbacks for this channel
+have run to completion. If callbacks take a lock (mutex) then it is the
+user's responsibility to ensure that this lock is not held when
+ca_clear_channel() is called, otherwise a deadlock may ensue.
+(See also ca_clear_subscription().)
+
Arguments
CHID
@@ -3200,6 +3214,13 @@ and not forwarded to the server until one of ca_flush_io(), c
ca_pend_event(), or ca_sg_block() are called. This allows several requests to be
efficiently sent together in one message.
+Note: This operation blocks until any user callbacks for this channel
+have run to completion. If callbacks take a lock (mutex) then it is the
+user's responsibility to ensure that this lock is not held when
+ca_clear_subscription() is called, otherwise a deadlock may
+ensue. (See also ca_clear_channel().)
+
Arguments
- EVID
From 3f3696fb91e31ca654b1b472190297a8451364ae Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 3 May 2018 14:28:44 -0500
Subject: [PATCH 17/18] dbStatic: Prevent modifying a NAME field using a DB
file
Fixes LP: #1597809
---
src/dbStatic/dbLexRoutines.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c
index db95cc61f..87bb7295f 100644
--- a/src/dbStatic/dbLexRoutines.c
+++ b/src/dbStatic/dbLexRoutines.c
@@ -974,6 +974,12 @@ static void dbRecordField(char *name,char *value)
yyerror(NULL);
return;
}
+ if (pdbentry->indfield == 0) {
+ epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
+ dbGetRecordName(pdbentry));
+ yyerror(NULL);
+ return;
+ }
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
status = dbPutString(pdbentry,value);
if(status) {
From 116c90c2ea1e3e542ee5d0d42349a64b1f4097b1 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 3 May 2018 14:40:12 -0500
Subject: [PATCH 18/18] Reformatting, no code changes
---
src/dbStatic/dbLexRoutines.c | 67 ++++++++++++++++++------------------
1 file changed, 34 insertions(+), 33 deletions(-)
diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c
index 87bb7295f..91437b342 100644
--- a/src/dbStatic/dbLexRoutines.c
+++ b/src/dbStatic/dbLexRoutines.c
@@ -960,29 +960,29 @@ static void dbRecordHead(char *recordType, char *name, int visible)
static void dbRecordField(char *name,char *value)
{
- DBENTRY *pdbentry;
- tempListNode *ptempListNode;
- long status;
+ DBENTRY *pdbentry;
+ tempListNode *ptempListNode;
+ long status;
- if(duplicate) return;
+ if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbFindField(pdbentry,name);
- if(status) {
- epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
- dbGetRecordName(pdbentry), name);
- yyerror(NULL);
- return;
+ if (status) {
+ epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
+ dbGetRecordName(pdbentry), name);
+ yyerror(NULL);
+ return;
}
if (pdbentry->indfield == 0) {
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
- dbGetRecordName(pdbentry));
+ dbGetRecordName(pdbentry));
yyerror(NULL);
return;
}
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
status = dbPutString(pdbentry,value);
- if(status) {
+ if (status) {
epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
@@ -992,33 +992,33 @@ static void dbRecordField(char *name,char *value)
static void dbRecordInfo(char *name, char *value)
{
- DBENTRY *pdbentry;
- tempListNode *ptempListNode;
- long status;
+ DBENTRY *pdbentry;
+ tempListNode *ptempListNode;
+ long status;
- if(duplicate) return;
+ if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbPutInfo(pdbentry,name,value);
- if(status) {
- epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
+ if (status) {
+ epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
- yyerror(NULL);
- return;
+ yyerror(NULL);
+ return;
}
}
static void dbRecordAlias(char *name)
{
- DBENTRY *pdbentry;
- tempListNode *ptempListNode;
- long status;
+ DBENTRY *pdbentry;
+ tempListNode *ptempListNode;
+ long status;
- if(duplicate) return;
+ if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbCreateAlias(pdbentry, name);
- if(status) {
+ if (status) {
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
name, dbGetRecordName(pdbentry));
yyerror(NULL);
@@ -1028,15 +1028,16 @@ static void dbRecordAlias(char *name)
static void dbAlias(char *name, char *alias)
{
- DBENTRY dbEntry;
- DBENTRY *pdbEntry = &dbEntry;
+ DBENTRY dbEntry;
+ DBENTRY *pdbEntry = &dbEntry;
dbInitEntry(pdbbase, pdbEntry);
if (dbFindRecord(pdbEntry, name)) {
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
alias, name);
yyerror(NULL);
- } else if (dbCreateAlias(pdbEntry, alias)) {
+ }
+ else if (dbCreateAlias(pdbEntry, alias)) {
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
alias, name);
yyerror(NULL);
@@ -1046,14 +1047,14 @@ static void dbAlias(char *name, char *alias)
static void dbRecordBody(void)
{
- DBENTRY *pdbentry;
+ DBENTRY *pdbentry;
- if(duplicate) {
- duplicate = FALSE;
- return;
+ if (duplicate) {
+ duplicate = FALSE;
+ return;
}
pdbentry = (DBENTRY *)popFirstTemp();
- if(ellCount(&tempList))
- yyerrorAbort("dbRecordBody: tempList not empty");
+ if (ellCount(&tempList))
+ yyerrorAbort("dbRecordBody: tempList not empty");
dbFreeEntry(pdbentry);
}