Tcl exception codes cleanup, shutdown command amendments 00/2600/4
authorPaul Fertser <fercerpav@gmail.com>
Fri, 13 Mar 2015 13:32:53 +0000 (16:32 +0300)
committerPaul Fertser <fercerpav@gmail.com>
Tue, 14 Apr 2015 11:11:48 +0000 (12:11 +0100)
This patch might influence openocd Tcl commands behaviour in subtle
ways, please give it a nice testing.

The idea is that if an OpenOCD Tcl command returns an error, an
exception is raised, and then the return code is propogated all the
way up (or to the "catch" if present). This allows to detect
"shutdown" which is not actually an error but has to raise an
exception to stop execution of the commands that follow it in the
script.

openocd_thread special-cases shutdown because it should then terminate
OpenOCD with a success error code, unless shutdown was called with an
optional "error" argument which means terminate with a non-zero exit
code.

Change-Id: I7b6fa8a2e24c947dc45d8def0008b4b007c478b3
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/2600
Tested-by: jenkins
Reviewed-by: Juha Niskanen <juha.niskanen@haltian.com>
Reviewed-by: Jens Bauer <jens@gpio.dk>
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
doc/openocd.texi
src/flash/startup.tcl
src/helper/command.c
src/helper/startup.tcl
src/openocd.c
src/server/server.c

index 4bec637f3ee29c1bcbfe0c585c3ba3f57cf8be5f..e418e05005e27cc30e7a48e59aaf2902f2691df2 100644 (file)
@@ -6486,8 +6486,10 @@ Useful in connection with script files
 (@command{script} command and @command{target_name} configuration).
 @end deffn
 
-@deffn Command shutdown
-Close the OpenOCD daemon, disconnecting all clients (GDB, telnet, other).
+@deffn Command shutdown [@option{error}]
+Close the OpenOCD daemon, disconnecting all clients (GDB, telnet,
+other). If option @option{error} is used, OpenOCD will return a
+non-zero exit code to the parent process.
 @end deffn
 
 @anchor{debuglevel}
index 7a96a3e3b8496dd14bccb2de3fe999f2cebc5bf8..fbb8d8ee498249538aed598e186e31a1404479a3 100644 (file)
@@ -8,8 +8,8 @@
 
 proc program_error {description exit} {
        if {$exit == 1} {
-               echo $description
-               shutdown
+               echo $description
+               shutdown error
        }
 
        error $description
index 9d19cff4f870630555d545565bfdbf0e7a445bfa..a0aa9e857e38bd81ffbd371f3dc001ec152c6503 100644 (file)
@@ -121,7 +121,7 @@ static int command_retval_set(Jim_Interp *interp, int retval)
        if (return_retval != NULL)
                *return_retval = retval;
 
-       return (retval == ERROR_OK) ? JIM_OK : JIM_ERR;
+       return (retval == ERROR_OK) ? JIM_OK : retval;
 }
 
 extern struct command_context *global_cmd_ctx;
@@ -659,24 +659,7 @@ int command_run_line(struct command_context *context, char *line)
                }
                Jim_DeleteAssocData(interp, "context");
        }
-       if (retcode == JIM_ERR) {
-               if (retval == ERROR_COMMAND_CLOSE_CONNECTION) {
-                       /* Shutdown request is not an error */
-                       return ERROR_OK;
-               } else {
-                       /* We do not print the connection closed error message */
-                       Jim_MakeErrorMessage(interp);
-                       LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
-               }
-               if (retval == ERROR_OK) {
-                       /* It wasn't a low level OpenOCD command that failed */
-                       return ERROR_FAIL;
-               }
-               return retval;
-       } else if (retcode == JIM_EXIT) {
-               /* ignore.
-                * exit(Jim_GetExitCode(interp)); */
-       } else {
+       if (retcode == JIM_OK) {
                const char *result;
                int reslen;
 
@@ -696,7 +679,22 @@ int command_run_line(struct command_context *context, char *line)
                        LOG_USER_N("\n");
                }
                retval = ERROR_OK;
+       } else if (retcode == JIM_EXIT) {
+               /* ignore.
+                * exit(Jim_GetExitCode(interp)); */
+       } else if (retcode == ERROR_COMMAND_CLOSE_CONNECTION) {
+               return retcode;
+       } else {
+               Jim_MakeErrorMessage(interp);
+               LOG_USER("%s", Jim_GetString(Jim_GetResult(interp), NULL));
+
+               if (retval == ERROR_OK) {
+                       /* It wasn't a low level OpenOCD command that failed */
+                       return ERROR_FAIL;
+               }
+               return retval;
        }
+
        return retval;
 }
 
index 926d26b637fb3072ca6481c278a106f12fb3fef7..4ca2cabc26b91df3491aeba99871e597e4f113b6 100644 (file)
@@ -16,10 +16,12 @@ proc exit {} {
 proc ocd_bouncer {name args} {
        set cmd [format "ocd_%s" $name]
        set type [eval ocd_command type $cmd $args]
+       set errcode error
        if {$type == "native"} {
                return [eval $cmd $args]
        } else {if {$type == "simple"} {
-               if {[catch {eval $cmd $args}] == 0} {
+               set errcode [catch {eval $cmd $args}]
+               if {$errcode == 0} {
                        return ""
                } else {
                        # 'classic' commands output error message as part of progress output
@@ -32,7 +34,7 @@ proc ocd_bouncer {name args} {
        } else {
                set errmsg [format "invalid subcommand \"%s\"" $args]
        }}}
-       return -code error $errmsg
+       return -code $errcode $errmsg
 }
 
 # Try flipping / and \ to find file if the filename does not
index b0dd21ab2c82bd7a72e038d7801b37bf97eeff42..4d4dc2c83d1a9dd4156dc5b80cc7063192d1dc01 100644 (file)
@@ -283,7 +283,9 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct
                return ERROR_FAIL;
 
        ret = parse_config_file(cmd_ctx);
-       if (ret != ERROR_OK)
+       if (ret == ERROR_COMMAND_CLOSE_CONNECTION)
+               return ERROR_OK;
+       else if (ret != ERROR_OK)
                return ERROR_FAIL;
 
        ret = server_init(cmd_ctx);
@@ -296,9 +298,15 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct
                        return ERROR_FAIL;
        }
 
-       server_loop(cmd_ctx);
+       ret = server_loop(cmd_ctx);
+
+       int last_signal = server_quit();
+       if (last_signal != ERROR_OK)
+               return last_signal;
 
-       return server_quit();
+       if (ret != ERROR_OK)
+               return ERROR_FAIL;
+       return ERROR_OK;
 }
 
 /* normally this is the main() function entry, but if OpenOCD is linked
index 73d8b5b652c97636055d72243574fc61e70d72ef..7e90d89fd2d6af7d1a3cc89b80a70186e84a6c6e 100644 (file)
@@ -44,7 +44,8 @@
 
 static struct service *services;
 
-/* shutdown_openocd == 1: exit the main event loop, and quit the debugger */
+/* shutdown_openocd == 1: exit the main event loop, and quit the
+ * debugger; 2: quit with non-zero return code */
 static int shutdown_openocd;
 
 /* store received signal to exit application by killing ourselves */
@@ -499,7 +500,7 @@ int server_loop(struct command_context *command_context)
 #endif
        }
 
-       return ERROR_OK;
+       return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL;
 }
 
 #ifdef _WIN32
@@ -608,6 +609,13 @@ COMMAND_HANDLER(handle_shutdown_command)
 
        shutdown_openocd = 1;
 
+       if (CMD_ARGC == 1) {
+               if (!strcmp(CMD_ARGV[0], "error")) {
+                       shutdown_openocd = 2;
+                       return ERROR_FAIL;
+               }
+       }
+
        return ERROR_COMMAND_CLOSE_CONNECTION;
 }
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)