Skip to content
Permalink
Browse files
GUACAMOLE-384: Merge fix for potential segfault if SSH connection is …
…closed while output is still being written to the terminal.
  • Loading branch information
mike-jumper committed Jan 23, 2018
2 parents 8c844e6 + d33bd8d commit db85163e20a253dae1daffd0dd6b7ab6beb1ed6d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 3 deletions.
@@ -70,8 +70,12 @@ int guac_ssh_client_free_handler(guac_client* client) {

/* Free terminal (which may still be using term_channel) */
if (ssh_client->term != NULL) {
guac_terminal_free(ssh_client->term);
/* Stop the terminal to unblock any pending reads/writes */
guac_terminal_stop(ssh_client->term);

/* Wait ssh_client_thread to finish before freeing the terminal */
pthread_join(ssh_client->client_thread, NULL);
guac_terminal_free(ssh_client->term);
}

/* Free terminal channel now that the terminal is finished */
@@ -162,8 +162,14 @@ void* ssh_input_thread(void* data) {
pthread_mutex_lock(&(ssh_client->term_channel_lock));
libssh2_channel_write(ssh_client->term_channel, buffer, bytes_read);
pthread_mutex_unlock(&(ssh_client->term_channel_lock));

/* Make sure ssh_input_thread can be terminated anyway */
if (client->state == GUAC_CLIENT_STOPPING)
break;
}

/* Stop the client so that ssh_client_thread can be terminated */
guac_client_stop(client);
return NULL;

}
@@ -340,6 +346,12 @@ void* ssh_client_thread(void* data) {
break;
}

/* Client is stopping, break the loop */
if (client->state == GUAC_CLIENT_STOPPING) {
pthread_mutex_unlock(&(ssh_client->term_channel_lock));
break;
}

/* Send keepalive at configured interval */
if (settings->server_alive_interval > 0) {
timeout = 0;
@@ -410,11 +410,23 @@ guac_terminal* guac_terminal_create(guac_client* client,

}

void guac_terminal_stop(guac_terminal* term) {

/* Close input pipe and set fds to invalid */
if (term->stdin_pipe_fd[1] != -1) {
close(term->stdin_pipe_fd[1]);
term->stdin_pipe_fd[1] = -1;
}
if (term->stdin_pipe_fd[0] != -1) {
close(term->stdin_pipe_fd[0]);
term->stdin_pipe_fd[0] = -1;
}
}

void guac_terminal_free(guac_terminal* term) {

/* Close user input pipe */
close(term->stdin_pipe_fd[1]);
close(term->stdin_pipe_fd[0]);
guac_terminal_stop(term);

/* Wait for render thread to finish */
pthread_join(term->thread, NULL);
@@ -491,6 +491,15 @@ int guac_terminal_render_frame(guac_terminal* terminal);
*/
int guac_terminal_read_stdin(guac_terminal* terminal, char* c, int size);

/**
* Manually stop the terminal to forcibly unblock any pending reads/writes,
* e.g. forcing guac_terminal_read_stdin() to return and cease all terminal I/O.
*
* @param term
* The terminal to stop.
*/
void guac_terminal_stop(guac_terminal* term);

/**
* Notifies the terminal that an event has occurred and the terminal should
* flush itself when reasonable.

0 comments on commit db85163

Please sign in to comment.