GUACAMOLE-180: Make common display threadsafe.

This commit is contained in:
Michael Jumper 2016-09-26 13:06:56 -07:00
parent b7e0e080da
commit 5d1de67a0c
2 changed files with 45 additions and 10 deletions

View File

@ -26,6 +26,8 @@
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/socket.h> #include <guacamole/socket.h>
#include <pthread.h>
/** /**
* A list element representing a pairing of a Guacamole layer with a * A list element representing a pairing of a Guacamole layer with a
* corresponding guac_common_surface which wraps that layer. Adjacent layers * corresponding guac_common_surface which wraps that layer. Adjacent layers
@ -97,6 +99,13 @@ typedef struct guac_common_display {
*/ */
guac_common_display_layer* buffers; guac_common_display_layer* buffers;
/**
* Mutex which is locked internally when access to the display must be
* synchronized. All public functions of guac_common_display should be
* considered threadsafe.
*/
pthread_mutex_t _lock;
} guac_common_display; } guac_common_display;
/** /**

View File

@ -24,6 +24,7 @@
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/socket.h> #include <guacamole/socket.h>
#include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -106,6 +107,8 @@ guac_common_display* guac_common_display_alloc(guac_client* client,
if (display == NULL) if (display == NULL)
return NULL; return NULL;
pthread_mutex_init(&display->_lock, NULL);
/* Associate display with given client */ /* Associate display with given client */
display->client = client; display->client = client;
@ -135,6 +138,7 @@ void guac_common_display_free(guac_common_display* display) {
guac_common_display_free_layers(display->buffers, display->client); guac_common_display_free_layers(display->buffers, display->client);
guac_common_display_free_layers(display->layers, display->client); guac_common_display_free_layers(display->layers, display->client);
pthread_mutex_destroy(&display->_lock);
free(display); free(display);
} }
@ -142,6 +146,8 @@ void guac_common_display_free(guac_common_display* display) {
void guac_common_display_dup(guac_common_display* display, guac_user* user, void guac_common_display_dup(guac_common_display* display, guac_user* user,
guac_socket* socket) { guac_socket* socket) {
pthread_mutex_lock(&display->_lock);
/* Sunchronize shared cursor */ /* Sunchronize shared cursor */
guac_common_cursor_dup(display->cursor, user, socket); guac_common_cursor_dup(display->cursor, user, socket);
@ -152,10 +158,14 @@ void guac_common_display_dup(guac_common_display* display, guac_user* user,
guac_common_display_dup_layers(display->layers, user, socket); guac_common_display_dup_layers(display->layers, user, socket);
guac_common_display_dup_layers(display->buffers, user, socket); guac_common_display_dup_layers(display->buffers, user, socket);
pthread_mutex_unlock(&display->_lock);
} }
void guac_common_display_flush(guac_common_display* display) { void guac_common_display_flush(guac_common_display* display) {
pthread_mutex_lock(&display->_lock);
guac_common_display_layer* current = display->layers; guac_common_display_layer* current = display->layers;
/* Flush all surfaces */ /* Flush all surfaces */
@ -166,6 +176,8 @@ void guac_common_display_flush(guac_common_display* display) {
guac_common_surface_flush(display->default_surface); guac_common_surface_flush(display->default_surface);
pthread_mutex_unlock(&display->_lock);
} }
/** /**
@ -246,42 +258,50 @@ static void guac_common_display_remove_layer(guac_common_display_layer** head,
guac_common_display_layer* guac_common_display_alloc_layer( guac_common_display_layer* guac_common_display_alloc_layer(
guac_common_display* display, int width, int height) { guac_common_display* display, int width, int height) {
guac_layer* layer; pthread_mutex_lock(&display->_lock);
guac_common_surface* surface;
/* Allocate Guacamole layer */ /* Allocate Guacamole layer */
layer = guac_client_alloc_layer(display->client); guac_layer* layer = guac_client_alloc_layer(display->client);
/* Allocate corresponding surface */ /* Allocate corresponding surface */
surface = guac_common_surface_alloc(display->client, guac_common_surface* surface = guac_common_surface_alloc(display->client,
display->client->socket, layer, width, height); display->client->socket, layer, width, height);
/* Add layer and surface to list */ /* Add layer and surface to list */
return guac_common_display_add_layer(&display->layers, layer, surface); guac_common_display_layer* display_layer =
guac_common_display_add_layer(&display->layers, layer, surface);
pthread_mutex_unlock(&display->_lock);
return display_layer;
} }
guac_common_display_layer* guac_common_display_alloc_buffer( guac_common_display_layer* guac_common_display_alloc_buffer(
guac_common_display* display, int width, int height) { guac_common_display* display, int width, int height) {
guac_layer* buffer; pthread_mutex_lock(&display->_lock);
guac_common_surface* surface;
/* Allocate Guacamole buffer */ /* Allocate Guacamole buffer */
buffer = guac_client_alloc_buffer(display->client); guac_layer* buffer = guac_client_alloc_buffer(display->client);
/* Allocate corresponding surface */ /* Allocate corresponding surface */
surface = guac_common_surface_alloc(display->client, guac_common_surface* surface = guac_common_surface_alloc(display->client,
display->client->socket, buffer, width, height); display->client->socket, buffer, width, height);
/* Add buffer and surface to list */ /* Add buffer and surface to list */
return guac_common_display_add_layer(&display->buffers, buffer, surface); guac_common_display_layer* display_layer =
guac_common_display_add_layer(&display->buffers, buffer, surface);
pthread_mutex_unlock(&display->_lock);
return display_layer;
} }
void guac_common_display_free_layer(guac_common_display* display, void guac_common_display_free_layer(guac_common_display* display,
guac_common_display_layer* display_layer) { guac_common_display_layer* display_layer) {
pthread_mutex_lock(&display->_lock);
/* Remove list element from list */ /* Remove list element from list */
guac_common_display_remove_layer(&display->layers, display_layer); guac_common_display_remove_layer(&display->layers, display_layer);
@ -292,11 +312,15 @@ void guac_common_display_free_layer(guac_common_display* display,
/* Free list element */ /* Free list element */
free(display_layer); free(display_layer);
pthread_mutex_unlock(&display->_lock);
} }
void guac_common_display_free_buffer(guac_common_display* display, void guac_common_display_free_buffer(guac_common_display* display,
guac_common_display_layer* display_buffer) { guac_common_display_layer* display_buffer) {
pthread_mutex_lock(&display->_lock);
/* Remove list element from list */ /* Remove list element from list */
guac_common_display_remove_layer(&display->buffers, display_buffer); guac_common_display_remove_layer(&display->buffers, display_buffer);
@ -307,5 +331,7 @@ void guac_common_display_free_buffer(guac_common_display* display,
/* Free list element */ /* Free list element */
free(display_buffer); free(display_buffer);
pthread_mutex_unlock(&display->_lock);
} }