mdavidsaver has proposed merging ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0.
Requested reviews:
Bruce Hill (bhill)
For more details, see:
https://code.launchpad.net/~epics-core/epics-base/+git/Com/+merge/366876
Add basic (literally?) error handling to iocsh.
1. Add the iocsh command "on error ..." with options to "continue" (the default), "break" (return w/ error code), "halt", and "wait ###".
2. Catch c++ exceptions and treat as an error.
3. Add iocshSetError() for use in C code.
Opening a iocsh script with "on error halt" will act similarly to:
https://code.launchpad.net/~bhill/epics-base/+git/epics-base/+merge/366606
The main difference is that:
1. More options in how errors are treated.
2. Errors on unknown iocsh commands.
3. Modifies *CallFunc() wrappers, not functions.
--
Your team EPICS Core Developers is subscribed to branch epics-base:7.0.
diff --git a/modules/database/src/ioc/as/asIocRegister.c b/modules/database/src/ioc/as/asIocRegister.c
index 16cba90..d5926a5 100644
--- a/modules/database/src/ioc/as/asIocRegister.c
+++ b/modules/database/src/ioc/as/asIocRegister.c
@@ -39,7 +39,7 @@ static void asSetSubstitutionsCallFunc(const iocshArgBuf *args)
static const iocshFuncDef asInitFuncDef = {"asInit",0};
static void asInitCallFunc(const iocshArgBuf *args)
{
- asInit();
+ iocshSetError(asInit());
}
/* asdbdump */
diff --git a/modules/database/src/ioc/db/dbIocRegister.c b/modules/database/src/ioc/db/dbIocRegister.c
index c40af92..afb3115 100644
--- a/modules/database/src/ioc/db/dbIocRegister.c
+++ b/modules/database/src/ioc/db/dbIocRegister.c
@@ -39,7 +39,7 @@ static const iocshFuncDef dbLoadDatabaseFuncDef =
{"dbLoadDatabase",3,dbLoadDatabaseArgs};
static void dbLoadDatabaseCallFunc(const iocshArgBuf *args)
{
- dbLoadDatabase(args[0].sval,args[1].sval,args[2].sval);
+ iocshSetError(dbLoadDatabase(args[0].sval,args[1].sval,args[2].sval));
}
/* dbLoadRecords */
@@ -49,7 +49,7 @@ static const iocshArg * const dbLoadRecordsArgs[2] = {&dbLoadRecordsArg0,&dbLoad
static const iocshFuncDef dbLoadRecordsFuncDef = {"dbLoadRecords",2,dbLoadRecordsArgs};
static void dbLoadRecordsCallFunc(const iocshArgBuf *args)
{
- dbLoadRecords(args[0].sval,args[1].sval);
+ iocshSetError(dbLoadRecords(args[0].sval,args[1].sval));
}
/* dbb */
diff --git a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c
index 201a323..879f67e 100644
--- a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c
+++ b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c
@@ -22,7 +22,7 @@ static const iocshFuncDef dbLoadTemplateFuncDef =
{"dbLoadTemplate", 2, dbLoadTemplateArgs};
static void dbLoadTemplateCallFunc(const iocshArgBuf *args)
{
- dbLoadTemplate(args[0].sval, args[1].sval);
+ iocshSetError(dbLoadTemplate(args[0].sval, args[1].sval));
}
diff --git a/modules/database/src/ioc/misc/miscIocRegister.c b/modules/database/src/ioc/misc/miscIocRegister.c
index 6c08ef0..4dffdfc 100644
--- a/modules/database/src/ioc/misc/miscIocRegister.c
+++ b/modules/database/src/ioc/misc/miscIocRegister.c
@@ -22,28 +22,28 @@
static const iocshFuncDef iocInitFuncDef = {"iocInit",0,NULL};
static void iocInitCallFunc(const iocshArgBuf *args)
{
- iocInit();
+ iocshSetError(iocInit());
}
/* iocBuild */
static const iocshFuncDef iocBuildFuncDef = {"iocBuild",0,NULL};
static void iocBuildCallFunc(const iocshArgBuf *args)
{
- iocBuild();
+ iocshSetError(iocBuild());
}
/* iocRun */
static const iocshFuncDef iocRunFuncDef = {"iocRun",0,NULL};
static void iocRunCallFunc(const iocshArgBuf *args)
{
- iocRun();
+ iocshSetError(iocRun());
}
/* iocPause */
static const iocshFuncDef iocPauseFuncDef = {"iocPause",0,NULL};
static void iocPauseCallFunc(const iocshArgBuf *args)
{
- iocPause();
+ iocshSetError(iocPause());
}
/* coreRelease */
@@ -77,7 +77,7 @@ static const iocshArg * const systemArgs[] = {&systemArg0};
static const iocshFuncDef systemFuncDef = {"system",1,systemArgs};
static void systemCallFunc(const iocshArgBuf *args)
{
- system(args[0].sval);
+ iocshSetError(system(args[0].sval));
}
#endif
diff --git a/modules/database/src/tools/registerRecordDeviceDriver.pl b/modules/database/src/tools/registerRecordDeviceDriver.pl
index 02bb9b7..10147db 100644
--- a/modules/database/src/tools/registerRecordDeviceDriver.pl
+++ b/modules/database/src/tools/registerRecordDeviceDriver.pl
@@ -277,7 +277,7 @@ static const iocshFuncDef rrddFuncDef =
{"$subname", 1, rrddArgs};
static void rrddCallFunc(const iocshArgBuf *)
{
- $subname(*iocshPpdbbase);
+ iocshSetError($subname(*iocshPpdbbase));
}
} // extern "C"
diff --git a/modules/libcom/src/iocsh/iocsh.cpp b/modules/libcom/src/iocsh/iocsh.cpp
index 0de90c8..2e64e8b 100644
--- a/modules/libcom/src/iocsh/iocsh.cpp
+++ b/modules/libcom/src/iocsh/iocsh.cpp
@@ -11,6 +11,8 @@
/* Heavily modified by Eric Norum Date: 03MAY2000 */
/* Adapted to C++ by Eric Norum Date: 18DEC2000 */
+#include <exception>
+
#include <stddef.h>
#include <string.h>
#include <stdio.h>
@@ -56,7 +58,7 @@ static char iocshVarID[] = "iocshVar";
extern "C" { static void varCallFunc(const iocshArgBuf *); }
static epicsMutexId iocshTableMutex;
static epicsThreadOnceId iocshOnceId = EPICS_THREAD_ONCE_INIT;
-static epicsThreadPrivateId iocshMacroHandleId;
+static epicsThreadPrivateId iocshScopeId;
/*
* I/O redirection
@@ -76,7 +78,7 @@ struct iocshRedirect {
static void iocshOnce (void *)
{
iocshTableMutex = epicsMutexMustCreate ();
- iocshMacroHandleId = epicsThreadPrivateCreate();
+ iocshScopeId = epicsThreadPrivateCreate();
}
static void iocshInit (void)
@@ -496,6 +498,30 @@ static void helpCallFunc(const iocshArgBuf *args)
}
}
+typedef enum {
+ Continue,
+ Break,
+ Halt
+} OnError;
+
+typedef struct {
+ MAC_HANDLE *handle;
+ OnError onerr;
+ double timeout;
+ bool errored;
+} Scope;
+
+int iocshSetError(int err)
+{
+ Scope *scope;
+ if (err && iocshScopeId) {
+ scope = (Scope *) epicsThreadPrivateGet(iocshScopeId);
+
+ if(scope) scope->errored = 1;
+ }
+ return err;
+}
+
/*
* The body of the command interpreter
*/
@@ -524,8 +550,10 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
void *readlineContext = NULL;
int wasOkToBlock;
static const char * pairs[] = {"", "environ", NULL, NULL};
+ Scope *scope;
MAC_HANDLE *handle;
char ** defines = NULL;
+ int ret = 0;
iocshInit();
@@ -586,17 +614,20 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
/*
* Check for existing macro context or construct a new one.
*/
- handle = (MAC_HANDLE *) epicsThreadPrivateGet(iocshMacroHandleId);
+ scope = (Scope *) epicsThreadPrivateGet(iocshScopeId);
- if (handle == NULL) {
- if (macCreateHandle(&handle, pairs)) {
+ if (!scope) {
+ scope = (Scope*)calloc(1, sizeof(*scope));
+ if (!scope || macCreateHandle(&scope->handle, pairs)) {
errlogMessage("iocsh: macCreateHandle failed.");
free(redirects);
+ free(scope);
return -1;
}
- epicsThreadPrivateSet(iocshMacroHandleId, (void *) handle);
+ epicsThreadPrivateSet(iocshScopeId, (void *) scope);
}
+ handle = scope->handle;
macPushScope(handle);
macInstallMacros(handle, defines);
@@ -834,7 +865,17 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
for (int iarg = 0 ; ; ) {
if (iarg == piocshFuncDef->nargs) {
startRedirect(filename, lineno, redirects);
- (*found->def.func)(argBuf);
+ /* execute */
+ scope->errored = false;
+ try {
+ (*found->def.func)(argBuf);
+ } catch(std::exception& e){
+ fprintf(epicsGetStderr(), "c++ error: %s\n", e.what());
+ scope->errored = true;
+ } catch(...) {
+ fprintf(epicsGetStderr(), "c++ error unknown\n");
+ scope->errored = true;
+ }
break;
}
if (iarg >= argBufCapacity) {
@@ -868,15 +909,33 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
}
else {
showError(filename, lineno, "Command %s not found.", argv[0]);
+ scope->errored = true;
}
}
stopRedirect(filename, lineno, redirects);
+ if(!commandLine && !scope->errored) {
+ if(scope->onerr==Continue) {
+ } else if(scope->onerr==Break) {
+ ret = -1;
+ break;
+ } else if(scope->onerr==Halt) {
+ ret = -1;
+ if(scope->timeout<=0.0) {
+ epicsThreadSuspendSelf();
+ } else {
+ fprintf(epicsGetStderr(), "Wait %f sec\n", scope->timeout);
+ epicsThreadSleep(scope->timeout);
+ }
+ break;
+ }
+ }
}
macPopScope(handle);
if (handle->level == 0) {
macDeleteHandle(handle);
- epicsThreadPrivateSet(iocshMacroHandleId, NULL);
+ free(scope);
+ epicsThreadPrivateSet(iocshScopeId, NULL);
}
if (fp && (fp != stdin))
fclose (fp);
@@ -891,7 +950,7 @@ iocshBody (const char *pathname, const char *commandLine, const char *macros)
if (readlineContext)
epicsReadlineEnd(readlineContext);
epicsThreadSetOkToBlock(wasOkToBlock);
- return 0;
+ return ret;
}
/*
@@ -943,13 +1002,13 @@ iocshRun(const char *cmd, const char *macros)
void epicsShareAPI
iocshEnvClear(const char *name)
{
- MAC_HANDLE *handle;
+ Scope *scope;
- if (iocshMacroHandleId) {
- handle = (MAC_HANDLE *) epicsThreadPrivateGet(iocshMacroHandleId);
+ if (iocshScopeId) {
+ scope = (Scope *) epicsThreadPrivateGet(iocshScopeId);
- if (handle != NULL) {
- macPutValue(handle, name, NULL);
+ if (scope != NULL) {
+ macPutValue(scope->handle, name, NULL);
}
}
}
@@ -1054,6 +1113,41 @@ static void iocshRunCallFunc(const iocshArgBuf *args)
iocshRun(args[0].sval, args[1].sval);
}
+/* on */
+static const iocshArg onArg0 = { "...", iocshArgArgv };
+static const iocshArg *onArgs[1] = {&onArg0};
+static const iocshFuncDef onFuncDef = {"on", 1, onArgs};
+static void onCallFunc(const iocshArgBuf *args)
+{
+ Scope *scope = (Scope *) epicsThreadPrivateGet(iocshScopeId);
+
+ if(!scope || args->aval.ac<=2) {
+ } else if(strcmp(args->aval.av[1], "error")==0) {
+ if(args->aval.ac==2) {
+ } else if(strcmp(args->aval.av[2], "continue")==0) {
+ scope->onerr = Continue;
+ return;
+
+ } else if(strcmp(args->aval.av[2], "break")==0) {
+ scope->onerr = Break;
+ return;
+
+ } else if(strcmp(args->aval.av[2], "halt")==0) {
+ scope->onerr = Halt;
+ scope->timeout = 0.0;
+ return;
+
+ } else if(strcmp(args->aval.av[2], "wait")==0) {
+ scope->onerr = Halt;
+ if(args->aval.ac==3 || !epicsParseDouble(args->aval.av[3], &scope->timeout, NULL)) {
+ scope->timeout = 5.0;
+ }
+ return;
+ }
+ }
+ fprintf(epicsGetStderr(), "Invalid 'on'\n");
+}
+
/*
* Dummy internal commands -- register and install in command table
* so they show up in the help display
@@ -1083,6 +1177,7 @@ static void localRegister (void)
iocshRegister(&iocshCmdFuncDef,iocshCmdCallFunc);
iocshRegister(&iocshLoadFuncDef,iocshLoadCallFunc);
iocshRegister(&iocshRunFuncDef,iocshRunCallFunc);
+ iocshRegister(&onFuncDef, onCallFunc);
}
} /* extern "C" */
diff --git a/modules/libcom/src/iocsh/iocsh.h b/modules/libcom/src/iocsh/iocsh.h
index 84b38f2..2e8dc22 100644
--- a/modules/libcom/src/iocsh/iocsh.h
+++ b/modules/libcom/src/iocsh/iocsh.h
@@ -89,6 +89,8 @@ epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
epicsShareFunc int epicsShareAPI iocshLoad(const char *pathname, const char* macros);
epicsShareFunc int epicsShareAPI iocshRun(const char *cmd, const char* macros);
+epicsShareFunc int iocshSetError(int err);
+
/* Makes macros that shadow environment variables work correctly with epicsEnvSet */
epicsShareFunc void epicsShareAPI iocshEnvClear(const char *name);
diff --git a/modules/libcom/src/iocsh/libComRegister.c b/modules/libcom/src/iocsh/libComRegister.c
index b105ea1..11396e9 100644
--- a/modules/libcom/src/iocsh/libComRegister.c
+++ b/modules/libcom/src/iocsh/libComRegister.c
@@ -76,7 +76,7 @@ static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs};
static void chdirCallFunc(const iocshArgBuf *args)
{
if (args[0].sval == NULL ||
- chdir(args[0].sval)) {
+ iocshSetError(chdir(args[0].sval))) {
fprintf(stderr, "Invalid directory path, ignored\n");
}
}
- Replies:
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Ben Franksen via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Keenan Lang via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Keenan Lang via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Keenan Lang via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Bruce Hill via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Bruce Hill via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Keenan Lang via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Keenan Lang via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 Andrew Johnson via Core-talk
- [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 noreply--- via Core-talk
- Navigate by Date:
- Prev:
[Bug 1827225] Re: AppVeyor mingw builds broken (claiming missing epicsTempFile.obj) Ralph Lange via Core-talk
- Next:
Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
<2019>
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Build completed: EPICS Base base-3.15-390 AppVeyor via Core-talk
- Next:
Re: [Merge] ~epics-core/epics-base/+git/Com:iocsherr into epics-base:7.0 mdavidsaver via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
<2019>
2020
2021
2022
2023
2024
|