From 5e394e4928c3dcd408428a91e4e1adcd5ba87e3e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 20 Jan 2018 19:50:33 -0600 Subject: [PATCH] dbJLink: Handle NULL returned by jlif::alloc() better It might not mean out-of-memory, adjust error message. Add OOM and dbfType error checks to all jlif::alloc() routines. Change all IFDEBUG() in JLink types to use exported global variables. This allows debug messages to be output from the jlif::alloc() routines, since the jlink field isn't set when they're called. --- src/ioc/db/dbJLink.c | 16 ++++++++++------ src/std/link/links.dbd.pod | 38 ++++++++++++++++++++++---------------- src/std/link/lnkCalc.c | 22 +++++++++++++++++----- src/std/link/lnkConst.c | 28 ++++++++++++++++++---------- src/std/link/lnkState.c | 22 +++++++++++++++++----- 5 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c index ea054eee9..0bc8d6ba5 100644 --- a/src/ioc/db/dbJLink.c +++ b/src/ioc/db/dbJLink.c @@ -2,7 +2,7 @@ * Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* dbJLink.c */ @@ -241,25 +241,29 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) { return dbjl_return(parser, jlif_stop); } - dbmfFree(link_name); - pjlink = pjlif->alloc_jlink(parser->dbfType); if (!pjlink) { - errlogPrintf("dbJLinkInit: Out of memory\n"); + errlogPrintf("dbJLinkInit: Link type '%s' allocation failed. \n", + link_name); + dbmfFree(link_name); return dbjl_return(parser, jlif_stop); } + pjlink->pif = pjlif; - pjlink->parent = NULL; pjlink->parseDepth = 0; pjlink->debug = !!parser->lset_debug; - if (parser->pjlink) { /* We're starting a child link, save its parent */ pjlink->parent = parser->pjlink; } + else + pjlink->parent = NULL; + parser->pjlink = pjlink; parser->key_is_link = 0; + dbmfFree(link_name); + IFDEBUG(8) printf("dbjl_map_key: New %s@%p\n", pjlink ? pjlink->pif->name : "", pjlink); diff --git a/src/std/link/links.dbd.pod b/src/std/link/links.dbd.pod index 9b802b513..6eb8b77d3 100644 --- a/src/std/link/links.dbd.pod +++ b/src/std/link/links.dbd.pod @@ -33,15 +33,17 @@ database file syntax. =cut + link(const, lnkConstIf) +variable(lnkConst_debug, int) =head3 Constant Link C<"const"> -Constant links provide one or more values at link initalization time, but do not -return any data when their C routine is called. Most record types -support the use of constant links by calling C at -record initialization, which results in the constant value being loaded into the -target field at that time. +Constant links are input links that provide literal values at link initalization +time, but do not return any data when their C routine is called. +Most record types support the use of constant links on their input links by +calling C at record initialization, which results in +the constant value being loaded into the target field at that time. Note that for most record types (the C and C records are the main exceptions) it is pointless to set an input link to a constant link at @@ -72,14 +74,16 @@ converted to the desired double value at initialization, for example: =cut + link(calc, lnkCalcIf) +variable(lnkCalc_debug, int) =head3 Calculation Link C<"calc"> -Calculation links can perform simple mathematical expressions on scalar -(double-precision floating-point) values obtained from other link types and -return a single double-precision floating-point result. The expressions are -evaluated by the EPICS Calc engine, and up to 12 inputs can be provided. +Calculation links are input links that can evaluate mathematical expressions on +scalar (double- precision floating-point) values obtained from child links, and +return a double-precision floating-point result. The expressions are evaluated +by the EPICS Calc engine, and up to 12 inputs can be provided. =head4 Parameters @@ -132,13 +136,15 @@ atomically with the value of the input argument. =cut + link(state, lnkStateIf) +variable(lnkState_debug, int) =head3 dbState Link C<"state"> -A dbState link is one that reads or writes a boolean value from/to a named -global flag as implemented by the dbState facility in C. The link -type can invert the sense of the dbState flag if desired. +A dbState link is one that gets or puts a boolean value from/to a named global +flag as implemented by the dbState facility in C. The link type can +invert the sense of the dbState flag during the get or put if desired. The value of the named flag is read or written at the time of the link I/O operation. When reading a flag, the value returned by the link will be zero or @@ -156,10 +162,10 @@ mechanism. =head4 Parameters -The link address must be a string providing the name of the dbState object, with -an optional leading C charater to indicate the flag's value should be -inverted. The dbState object will be created when the link is initialized if it -doesn't already exist. +The link takes a single parameter which must be a string, providing the name of +the dbState object, with an optional leading C character to indicate that the +flag's value should be inverted. The dbState object will be created when the +link is initialized if it doesn't already exist. =head4 Examples diff --git a/src/std/link/lnkCalc.c b/src/std/link/lnkCalc.c index c63495df0..87f3b4a3e 100644 --- a/src/std/link/lnkCalc.c +++ b/src/std/link/lnkCalc.c @@ -40,7 +40,10 @@ typedef long (*FASTCONVERT)(); -#define IFDEBUG(n) if(clink->jlink.debug) +int lnkCalc_debug; +epicsExportAddress(int, lnkCalc_debug); + +#define IFDEBUG(n) if (lnkCalc_debug >= (n)) typedef struct calc_link { jlink jlink; /* embedded object */ @@ -77,10 +80,21 @@ static lset lnkCalc_lset; static jlink* lnkCalc_alloc(short dbfType) { - calc_link *clink = calloc(1, sizeof(struct calc_link)); + calc_link *clink; IFDEBUG(10) - printf("lnkCalc_alloc()\n"); + printf("lnkCalc_alloc(%d)\n", dbfType); + + if (dbfType != DBF_INLINK) { + errlogPrintf("lnkCalc: Only works with input links\n"); + return NULL; + } + + clink = calloc(1, sizeof(struct calc_link)); + if (!clink) { + errlogPrintf("lnkCalc: calloc() failed.\n"); + return NULL; + } clink->nArgs = 0; clink->pstate = ps_init; @@ -355,8 +369,6 @@ static void lnkCalc_end_child(jlink *parent, jlink *child) static struct lset* lnkCalc_get_lset(const jlink *pjlink) { - calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink); - IFDEBUG(10) printf("lnkCalc_get_lset(calc@%p)\n", pjlink); diff --git a/src/std/link/lnkConst.c b/src/std/link/lnkConst.c index c2eb032c1..881bf6bff 100644 --- a/src/std/link/lnkConst.c +++ b/src/std/link/lnkConst.c @@ -2,7 +2,7 @@ * Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* lnkConst.c */ @@ -22,7 +22,10 @@ #include "epicsExport.h" -#define IFDEBUG(n) if (clink->jlink.debug) +int lnkConst_debug; +epicsExportAddress(int, lnkConst_debug); + +#define IFDEBUG(n) if (lnkConst_debug >= (n)) typedef long (*FASTCONVERT)(); @@ -48,10 +51,21 @@ static lset lnkConst_lset; static jlink* lnkConst_alloc(short dbfType) { - const_link *clink = calloc(1, sizeof(*clink)); + const_link *clink; IFDEBUG(10) - printf("lnkConst_alloc()\n"); + printf("lnkConst_alloc(%d)\n", dbfType); + + if (dbfType != DBF_INLINK) { + errlogPrintf("lnkConst: Only works with input links\n"); + return NULL; + } + + clink = calloc(1, sizeof(*clink)); + if (!clink) { + errlogPrintf("lnkConst: calloc() failed.\n"); + return NULL; + } clink->type = s0; clink->nElems = 0; @@ -146,7 +160,6 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num) static jlif_result lnkConst_boolean(jlink *pjlink, int val) { - const_link *clink = CONTAINER(pjlink, const_link, jlink); IFDEBUG(10) printf("lnkConst_boolean(const@%p, %d)\n", pjlink, val); @@ -276,8 +289,6 @@ static jlif_result lnkConst_start_array(jlink *pjlink) static jlif_result lnkConst_end_array(jlink *pjlink) { - const_link *clink = CONTAINER(pjlink, const_link, jlink); - IFDEBUG(10) printf("lnkConst_end_array(const@%p)\n", pjlink); @@ -286,8 +297,6 @@ static jlif_result lnkConst_end_array(jlink *pjlink) static struct lset* lnkConst_get_lset(const jlink *pjlink) { - const_link *clink = CONTAINER(pjlink, const_link, jlink); - IFDEBUG(10) printf("lnkConst_get_lset(const@%p)\n", pjlink); @@ -629,4 +638,3 @@ static jlif lnkConstIf = { lnkConst_report, NULL }; epicsExportAddress(jlif, lnkConstIf); - diff --git a/src/std/link/lnkState.c b/src/std/link/lnkState.c index e24773727..160dc78ca 100644 --- a/src/std/link/lnkState.c +++ b/src/std/link/lnkState.c @@ -35,7 +35,10 @@ typedef long (*FASTCONVERT)(); -#define IFDEBUG(n) if(slink->jlink.debug) +int lnkState_debug; +epicsExportAddress(int, lnkState_debug); + +#define IFDEBUG(n) if (lnkState_debug >= (n)) typedef struct state_link { jlink jlink; /* embedded object */ @@ -52,10 +55,21 @@ static lset lnkState_lset; static jlink* lnkState_alloc(short dbfType) { - state_link *slink = calloc(1, sizeof(struct state_link)); + state_link *slink; IFDEBUG(10) - printf("lnkState_alloc()\n"); + printf("lnkState_alloc(%d)\n", dbfType); + + if (dbfType == DBF_FWDLINK) { + errlogPrintf("lnkState: DBF_FWDLINK not supported\n"); + return NULL; + } + + slink = calloc(1, sizeof(struct state_link)); + if (!slink) { + errlogPrintf("lnkState: calloc() failed.\n"); + return NULL; + } slink->name = NULL; slink->state = NULL; @@ -97,8 +111,6 @@ static jlif_result lnkState_string(jlink *pjlink, const char *val, size_t len) static struct lset* lnkState_get_lset(const jlink *pjlink) { - state_link *slink = CONTAINER(pjlink, struct state_link, jlink); - IFDEBUG(10) printf("lnkState_get_lset(state@%p)\n", pjlink);