diff --git a/modules/database/src/ioc/db/Makefile b/modules/database/src/ioc/db/Makefile index ebb78e229f..b081eec36d 100644 --- a/modules/database/src/ioc/db/Makefile +++ b/modules/database/src/ioc/db/Makefile @@ -68,6 +68,7 @@ HTMLS += dbCommonOutput.html dbCore_SRCS += dbLock.c dbCore_SRCS += dbAccess.c +dbCore_SRCS += dbAccessNoThrow.c dbCore_SRCS += dbBkpt.c dbCore_SRCS += dbChannel.c dbCore_SRCS += dbConstLink.c diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c index 512611cea6..f3302d9020 100644 --- a/modules/database/src/ioc/db/dbAccess.c +++ b/modules/database/src/ioc/db/dbAccess.c @@ -38,6 +38,7 @@ #include "caeventmask.h" #include "callback.h" #include "dbAccessDefs.h" +#include "dbAccessNoThrow.h" #include "dbAddr.h" #include "dbBase.h" #include "dbBkpt.h" @@ -928,7 +929,7 @@ long dbGet(DBADDR *paddr, short dbrType, if(!paddr->vfields || !(prset=dbGetRset(paddr))->get_vfield) return S_db_badDbrtype; - return prset->get_vfield(paddr, vfield); + return dbRecSupGetVFieldNoThrow(prset, paddr, vfield); } if (nRequest && *nRequest == 0) @@ -1345,7 +1346,7 @@ long dbPut(DBADDR *paddr, short dbrType, if(!paddr->vfields || !prset->put_vfield) return S_db_badDbrtype; - return prset->put_vfield(paddr, vfield); + return dbRecSupPutVFieldNoThrow(prset, paddr, vfield); } if (special == SPC_ATTRIBUTE || paddr->ro) diff --git a/modules/database/src/ioc/db/dbAccessNoThrow.cpp b/modules/database/src/ioc/db/dbAccessNoThrow.cpp new file mode 100644 index 0000000000..5dff48ca11 --- /dev/null +++ b/modules/database/src/ioc/db/dbAccessNoThrow.cpp @@ -0,0 +1,60 @@ +/*************************************************************************\ +* Copyright (c) 2021 Lucas Russo +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include + +#include "recSup.h" +#include "dbAccessDefs.h" +#include "errlog.h" +#include "dbAccessNoThrow.h" + +/* + * Maps possible excpetions to DB error codes. Using the + * "exception dispatcher" pattern. + */ +inline long dbExceptionToLong() +{ + try { + throw; + } + catch (std::exception& e) { + errlogPrintf("dbExceptionToLong: Unhandled exception %s: %s\n", + typeid(e).name(), e.what()); + return S_db_errArg; + } +} + +/* + * Pseudo variadic templates for use without C++11 features + */ + +template +long dbRecSupNoThrowWrapper(F f, T1 t1, T2 t2) { + try { + return f(t1, t2); + } + catch(...){ + return dbExceptionToLong(); + } +} + +/* + * Wraps all RecordSupport functions from throwable functions to no-throwable ones, + * without using C++11 features + * + * For use with C code + */ + +long dbRecSupGetVFieldNoThrow(rset *prset, struct dbAddr *paddr, struct VField *vfield) +{ + return dbRecSupNoThrowWrapper(prset->get_vfield, paddr, vfield); +} + +long dbRecSupPutVFieldNoThrow(rset *prset, struct dbAddr *paddr, const struct VField *vfield) +{ + return dbRecSupNoThrowWrapper(prset->put_vfield, paddr, vfield); +} diff --git a/modules/database/src/ioc/db/dbAccessNoThrow.h b/modules/database/src/ioc/db/dbAccessNoThrow.h new file mode 100644 index 0000000000..f06935f907 --- /dev/null +++ b/modules/database/src/ioc/db/dbAccessNoThrow.h @@ -0,0 +1,26 @@ +/*************************************************************************\ +* Copyright (c) 2021 Lucas Russo +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef INC_dbAccessNoThrow_H +#define INC_dbAccessNoThrow_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +DBCORE_API long dbRecSupGetVFieldNoThrow(rset *prset, + struct dbAddr *paddr, struct VField *vfield); +DBCORE_API long dbRecSupPutVFieldNoThrow(rset *prset, + struct dbAddr *paddr, const struct VField *vfield); + +#ifdef __cplusplus +} +#endif + +#endif /* INC_dbAccessNoThrow_H */