X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fserver%2Fserver.c;h=f8273d42d9effd559c03dd4269042bf8e2bf5f87;hp=46c860f4feeae30d96dd40ea73b61ff0121b0e6c;hb=9bcd2b2fa3709a6653ff2f7ea8d0af5d4be790f0;hpb=f02327d85953152743dbb02d9ceeaa5b59da9ebe diff --git a/src/server/server.c b/src/server/server.c index 46c860f4fe..f8273d42d9 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -46,9 +46,13 @@ 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,50 @@ 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; + } +} + +int remove_service(const char *name, const char *port) +{ + struct service *tmp; + struct service *prev; + + prev = services; + + for (tmp = services; tmp; prev = tmp, tmp = tmp->next) { + if (!strcmp(tmp->name, name) && !strcmp(tmp->port, port)) { + remove_connections(tmp); + + if (tmp == services) + services = tmp->next; + else + prev->next = tmp->next; + + if (tmp->type != CONNECTION_STDINOUT) + close_socket(tmp->fd); + + free(tmp->priv); + free_service(tmp); + + return ERROR_OK; + } + } + + return ERROR_OK; +} + static int remove_services(void) { struct service *c = services; @@ -353,6 +401,8 @@ static int remove_services(void) while (c) { struct service *next = c->next; + remove_connections(c); + if (c->name) free(c->name); @@ -396,7 +446,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 +538,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 +570,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 +588,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 +652,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 +698,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 +739,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 +800,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 };