Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-1850: Add locking around cursor to ensure cairo display is not used while being recreated. #456

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/common/common/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ typedef struct guac_common_cursor {
*/
guac_timestamp timestamp;

/**
* Lock which restricts simultaneous access to the cursor, guaranteeing
* ordered modifications to the cursor and that incompatible operations
* do not occur simultaneously. This lock is for internal use within the
* cursor only.
*/
pthread_mutex_t _lock;

} guac_common_cursor;

/**
Expand Down
21 changes: 21 additions & 0 deletions src/common/cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <guacamole/timestamp.h>
#include <guacamole/user.h>

#include <pthread.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -74,12 +75,16 @@ guac_common_cursor* guac_common_cursor_alloc(guac_client* client) {
cursor->x = 0;
cursor->y = 0;

pthread_mutex_init(&(cursor->_lock), NULL);

return cursor;

}

void guac_common_cursor_free(guac_common_cursor* cursor) {

pthread_mutex_destroy(&(cursor->_lock));

guac_client* client = cursor->client;
guac_layer* buffer = cursor->buffer;
cairo_surface_t* surface = cursor->surface;
Expand All @@ -102,6 +107,8 @@ void guac_common_cursor_free(guac_common_cursor* cursor) {
void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user,
guac_socket* socket) {

pthread_mutex_lock(&(cursor->_lock));

/* Synchronize location */
guac_protocol_send_mouse(socket, cursor->x, cursor->y, cursor->button_mask,
cursor->timestamp);
Expand All @@ -119,6 +126,8 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user,
cursor->buffer, 0, 0, cursor->width, cursor->height);
}

pthread_mutex_unlock(&(cursor->_lock));

guac_socket_flush(socket);

}
Expand Down Expand Up @@ -154,6 +163,8 @@ static void* guac_common_cursor_broadcast_state(guac_user* user,
void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user,
int x, int y, int button_mask) {

pthread_mutex_lock(&(cursor->_lock));

/* Update current user of cursor */
cursor->user = user;

Expand All @@ -169,6 +180,8 @@ void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user,
guac_client_foreach_user(cursor->client,
guac_common_cursor_broadcast_state, cursor);

pthread_mutex_unlock(&(cursor->_lock));

}

/**
Expand Down Expand Up @@ -212,6 +225,8 @@ static void guac_common_cursor_resize(guac_common_cursor* cursor,
void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy,
unsigned const char* data, int width, int height, int stride) {

pthread_mutex_lock(&(cursor->_lock));

/* Copy image data */
guac_common_cursor_resize(cursor, width, height, stride);
memcpy(cursor->image_buffer, data, height * stride);
Expand Down Expand Up @@ -242,6 +257,8 @@ void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy,

guac_socket_flush(cursor->client->socket);

pthread_mutex_unlock(&(cursor->_lock));

}

void guac_common_cursor_set_surface(guac_common_cursor* cursor, int hx, int hy,
Expand Down Expand Up @@ -298,9 +315,13 @@ void guac_common_cursor_set_blank(guac_common_cursor* cursor) {
void guac_common_cursor_remove_user(guac_common_cursor* cursor,
guac_user* user) {

pthread_mutex_lock(&(cursor->_lock));

/* Disassociate from given user */
if (cursor->user == user)
cursor->user = NULL;

pthread_mutex_unlock(&(cursor->_lock));

}