server/server: Remove all exit() calls

With this patch OpenOCD shuts down properly when errors occur in the
server instead of just calling exit().

Change-Id: I2ae1a6153dafc88667951cab9152941cb487be85
Signed-off-by: Marc Schink <openocd-dev@marcschink.de>
Reviewed-on: http://openocd.zylin.com/3223
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
Tested-by: jenkins
gitignore-build
Marc Schink 2016-01-24 20:58:24 +01:00 committed by Freddie Chopin
parent 99db18a995
commit b43b95e460
3 changed files with 52 additions and 23 deletions

View File

@ -297,9 +297,11 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct
if (init_at_startup) { if (init_at_startup) {
ret = command_run_line(cmd_ctx, "init"); ret = command_run_line(cmd_ctx, "init");
if (ERROR_OK != ret) if (ERROR_OK != ret) {
server_quit();
return ERROR_FAIL; return ERROR_FAIL;
} }
}
ret = server_loop(cmd_ctx); ret = server_loop(cmd_ctx);

View File

@ -132,7 +132,9 @@ static int add_connection(struct service *service, struct command_context *cmd_c
free(out_file); free(out_file);
if (c->fd_out == -1) { if (c->fd_out == -1) {
LOG_ERROR("could not open %s", service->port); LOG_ERROR("could not open %s", service->port);
exit(1); command_done(c->cmd_ctx);
free(c);
return ERROR_FAIL;
} }
LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port); LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port);
@ -191,7 +193,13 @@ static int remove_connection(struct service *service, struct connection *connect
return ERROR_OK; return ERROR_OK;
} }
/* FIX! make service return error instead of invoking exit() */ static void free_service(struct service *c)
{
free(c->name);
free(c->port);
free(c);
}
int add_service(char *name, int add_service(char *name,
const char *port, const char *port,
int max_connections, int max_connections,
@ -235,7 +243,8 @@ int add_service(char *name,
c->fd = socket(AF_INET, SOCK_STREAM, 0); c->fd = socket(AF_INET, SOCK_STREAM, 0);
if (c->fd == -1) { if (c->fd == -1) {
LOG_ERROR("error creating socket: %s", strerror(errno)); LOG_ERROR("error creating socket: %s", strerror(errno));
exit(-1); free_service(c);
return ERROR_FAIL;
} }
setsockopt(c->fd, setsockopt(c->fd,
@ -255,7 +264,9 @@ int add_service(char *name,
hp = gethostbyname(bindto_name); hp = gethostbyname(bindto_name);
if (hp == NULL) { if (hp == NULL) {
LOG_ERROR("couldn't resolve bindto address: %s", bindto_name); LOG_ERROR("couldn't resolve bindto address: %s", bindto_name);
exit(-1); close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
} }
memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length); memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length);
} }
@ -263,7 +274,9 @@ int add_service(char *name,
if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) {
LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno)); LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno));
exit(-1); close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
} }
#ifndef _WIN32 #ifndef _WIN32
@ -281,7 +294,9 @@ int add_service(char *name,
if (listen(c->fd, 1) == -1) { if (listen(c->fd, 1) == -1) {
LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); LOG_ERROR("couldn't listen on socket: %s", strerror(errno));
exit(-1); close_socket(c->fd);
free_service(c);
return ERROR_FAIL;
} }
} else if (c->type == CONNECTION_STDINOUT) { } else if (c->type == CONNECTION_STDINOUT) {
c->fd = fileno(stdin); c->fd = fileno(stdin);
@ -302,13 +317,15 @@ int add_service(char *name,
/* we currenty do not support named pipes under win32 /* we currenty do not support named pipes under win32
* so exit openocd for now */ * so exit openocd for now */
LOG_ERROR("Named pipes currently not supported under this os"); LOG_ERROR("Named pipes currently not supported under this os");
exit(1); free_service(c);
return ERROR_FAIL;
#else #else
/* Pipe we're reading from */ /* Pipe we're reading from */
c->fd = open(c->port, O_RDONLY | O_NONBLOCK); c->fd = open(c->port, O_RDONLY | O_NONBLOCK);
if (c->fd == -1) { if (c->fd == -1) {
LOG_ERROR("could not open %s", c->port); LOG_ERROR("could not open %s", c->port);
exit(1); free_service(c);
return ERROR_FAIL;
} }
#endif #endif
} }
@ -425,7 +442,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
else { else {
LOG_ERROR("error during select: %s", strerror(errno)); LOG_ERROR("error during select: %s", strerror(errno));
exit(-1); return ERROR_FAIL;
} }
#else #else
@ -433,7 +450,7 @@ int server_loop(struct command_context *command_context)
FD_ZERO(&read_fds); FD_ZERO(&read_fds);
else { else {
LOG_ERROR("error during select: %s", strerror(errno)); LOG_ERROR("error during select: %s", strerror(errno));
exit(-1); return ERROR_FAIL;
} }
#endif #endif
} }
@ -552,7 +569,7 @@ int server_preinit(void)
if (WSAStartup(wVersionRequested, &wsaData) != 0) { if (WSAStartup(wVersionRequested, &wsaData) != 0) {
LOG_ERROR("Failed to Open Winsock"); LOG_ERROR("Failed to Open Winsock");
exit(-1); return ERROR_FAIL;
} }
/* register ctrl-c handler */ /* register ctrl-c handler */
@ -570,10 +587,18 @@ int server_preinit(void)
int server_init(struct command_context *cmd_ctx) int server_init(struct command_context *cmd_ctx)
{ {
int ret = tcl_init(); int ret = tcl_init();
if (ERROR_OK != ret)
if (ret != ERROR_OK)
return ret; return ret;
return telnet_init("Open On-Chip Debugger"); ret = telnet_init("Open On-Chip Debugger");
if (ret != ERROR_OK) {
remove_services();
return ret;
}
return ERROR_OK;
} }
int server_quit(void) int server_quit(void)

View File

@ -624,9 +624,8 @@ int telnet_init(char *banner)
return ERROR_OK; return ERROR_OK;
} }
struct telnet_service *telnet_service; struct telnet_service *telnet_service =
malloc(sizeof(struct telnet_service));
telnet_service = malloc(sizeof(struct telnet_service));
if (!telnet_service) { if (!telnet_service) {
LOG_ERROR("Failed to allocate telnet service."); LOG_ERROR("Failed to allocate telnet service.");
@ -635,13 +634,16 @@ int telnet_init(char *banner)
telnet_service->banner = banner; telnet_service->banner = banner;
return add_service("telnet", int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED,
telnet_port, telnet_new_connection, telnet_input, telnet_connection_closed,
CONNECTION_LIMIT_UNLIMITED,
telnet_new_connection,
telnet_input,
telnet_connection_closed,
telnet_service); telnet_service);
if (ret != ERROR_OK) {
free(telnet_service);
return ret;
}
return ERROR_OK;
} }
/* daemon configuration command telnet_port */ /* daemon configuration command telnet_port */