]> git.sur5r.net Git - openocd/blobdiff - src/server/server.c
server: explicitly call "shutdown" when catch CTRL-C or a signal
[openocd] / src / server / server.c
index 46c860f4feeae30d96dd40ea73b61ff0121b0e6c..bc5856cccbc88c03ce91ee0c18d052559fdd6aae 100644 (file)
 
 static struct service *services;
 
-/* shutdown_openocd == 1: exit the main event loop, and quit the
- * debugger; 2: quit with non-zero return code */
-static int shutdown_openocd;
+enum shutdown_reason {
+       CONTINUE_MAIN_LOOP,                     /* stay in main event loop */
+       SHUTDOWN_REQUESTED,                     /* set by shutdown command; exit the event loop and quit the debugger */
+       SHUTDOWN_WITH_ERROR_CODE,       /* set by shutdown command; quit with non-zero return code */
+       SHUTDOWN_WITH_SIGNAL_CODE       /* set by sig_handler; exec shutdown then exit with signal as return code */
+};
+static enum shutdown_reason shutdown_openocd = CONTINUE_MAIN_LOOP;
 
 /* store received signal to exit application by killing ourselves */
 static int last_signal;
@@ -259,7 +263,7 @@ int add_service(char *name,
                c->sin.sin_family = AF_INET;
 
                if (bindto_name == NULL)
-                       c->sin.sin_addr.s_addr = INADDR_ANY;
+                       c->sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
                else {
                        hp = gethostbyname(bindto_name);
                        if (hp == NULL) {
@@ -345,6 +349,21 @@ int add_service(char *name,
        return ERROR_OK;
 }
 
+static void remove_connections(struct service *service)
+{
+       struct connection *connection;
+
+       connection = service->connections;
+
+       while (connection) {
+               struct connection *tmp;
+
+               tmp = connection->next;
+               remove_connection(service, connection);
+               connection = tmp;
+       }
+}
+
 static int remove_services(void)
 {
        struct service *c = services;
@@ -353,6 +372,8 @@ static int remove_services(void)
        while (c) {
                struct service *next = c->next;
 
+               remove_connections(c);
+
                if (c->name)
                        free(c->name);
 
@@ -396,7 +417,7 @@ int server_loop(struct command_context *command_context)
                LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
 #endif
 
-       while (!shutdown_openocd) {
+       while (shutdown_openocd == CONTINUE_MAIN_LOOP) {
                /* monitor sockets for activity */
                fd_max = 0;
                FD_ZERO(&read_fds);
@@ -488,7 +509,7 @@ int server_loop(struct command_context *command_context)
                for (service = services; service; service = service->next) {
                        /* handle new connections on listeners */
                        if ((service->fd != -1)
-                           && (FD_ISSET(service->fd, &read_fds))) {
+                               && (FD_ISSET(service->fd, &read_fds))) {
                                if (service->max_connections != 0)
                                        add_connection(service, command_context);
                                else {
@@ -520,7 +541,7 @@ int server_loop(struct command_context *command_context)
                                                                        service->type == CONNECTION_STDINOUT) {
                                                                /* if connection uses a pipe then
                                                                 * shutdown openocd on error */
-                                                               shutdown_openocd = 1;
+                                                               shutdown_openocd = SHUTDOWN_REQUESTED;
                                                        }
                                                        remove_connection(service, c);
                                                        LOG_INFO("dropped '%s' connection",
@@ -538,29 +559,48 @@ int server_loop(struct command_context *command_context)
                MSG msg;
                while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                        if (msg.message == WM_QUIT)
-                               shutdown_openocd = 1;
+                               shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
                }
 #endif
        }
 
-       return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL;
+       /* when quit for signal or CTRL-C, run (eventually user implemented) "shutdown" */
+       if (shutdown_openocd == SHUTDOWN_WITH_SIGNAL_CODE)
+               command_run_line(command_context, "shutdown");
+
+       return shutdown_openocd == SHUTDOWN_WITH_ERROR_CODE ? ERROR_FAIL : ERROR_OK;
+}
+
+void sig_handler(int sig)
+{
+       /* store only first signal that hits us */
+       if (shutdown_openocd == CONTINUE_MAIN_LOOP) {
+               shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
+               last_signal = sig;
+               LOG_DEBUG("Terminating on Signal %d", sig);
+       } else
+               LOG_DEBUG("Ignored extra Signal %d", sig);
 }
 
+
 #ifdef _WIN32
 BOOL WINAPI ControlHandler(DWORD dwCtrlType)
 {
-       shutdown_openocd = 1;
+       shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE;
        return TRUE;
 }
-#endif
-
-void sig_handler(int sig)
+#else
+static void sigkey_handler(int sig)
 {
-       /* store only first signal that hits us */
-       if (!last_signal)
-               last_signal = sig;
-       shutdown_openocd = 1;
+       /* ignore keystroke generated signals if not in foreground process group */
+
+       if (tcgetpgrp(STDIN_FILENO) > 0)
+               sig_handler(sig);
+       else
+               LOG_DEBUG("Ignored Signal %d", sig);
 }
+#endif
+
 
 int server_preinit(void)
 {
@@ -583,8 +623,13 @@ int server_preinit(void)
        SetConsoleCtrlHandler(ControlHandler, TRUE);
 
        signal(SIGBREAK, sig_handler);
-#endif
        signal(SIGINT, sig_handler);
+#else
+       signal(SIGHUP, sig_handler);
+       signal(SIGPIPE, sig_handler);
+       signal(SIGQUIT, sigkey_handler);
+       signal(SIGINT, sigkey_handler);
+#endif
        signal(SIGTERM, sig_handler);
        signal(SIGABRT, sig_handler);
 
@@ -624,6 +669,13 @@ int server_quit(void)
        return last_signal;
 }
 
+void server_free(void)
+{
+       tcl_service_free();
+       telnet_service_free();
+       jsp_service_free();
+}
+
 void exit_on_signal(int sig)
 {
 #ifndef _WIN32
@@ -658,11 +710,11 @@ COMMAND_HANDLER(handle_shutdown_command)
 {
        LOG_USER("shutdown command invoked");
 
-       shutdown_openocd = 1;
+       shutdown_openocd = SHUTDOWN_REQUESTED;
 
        if (CMD_ARGC == 1) {
                if (!strcmp(CMD_ARGV[0], "error")) {
-                       shutdown_openocd = 2;
+                       shutdown_openocd = SHUTDOWN_WITH_ERROR_CODE;
                        return ERROR_FAIL;
                }
        }
@@ -719,7 +771,7 @@ static const struct command_registration server_command_handlers[] = {
                .mode = COMMAND_ANY,
                .usage = "[name]",
                .help = "Specify address by name on which to listen for "
-                   "incoming TCP/IP connections",
+                       "incoming TCP/IP connections",
        },
        COMMAND_REGISTRATION_DONE
 };