GUACAMOLE-1115: Do not hold general RDP message lock while waiting for print operations.
Holding the message lock will block handling of things like mouse and keyboard events, as the message lock must be acquired before sending the corresponding messages to the RDP server. If mouse and keyboard events are blocked, then handling of further Guacamole instructions like "ack" is also blocked. If the print job is blocked until an "ack" is received, this results in deadlock.
This commit is contained in:
parent
75a11b05b2
commit
d734bac590
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "print-job.h"
|
#include "print-job.h"
|
||||||
|
#include "rdp.h"
|
||||||
|
|
||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
@ -603,6 +604,9 @@ static void guac_rdp_print_job_read_filename(guac_rdp_print_job* job,
|
|||||||
int guac_rdp_print_job_write(guac_rdp_print_job* job,
|
int guac_rdp_print_job_write(guac_rdp_print_job* job,
|
||||||
void* buffer, int length) {
|
void* buffer, int length) {
|
||||||
|
|
||||||
|
guac_client* client = job->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* Create print job, if not yet created */
|
/* Create print job, if not yet created */
|
||||||
if (job->bytes_received == 0) {
|
if (job->bytes_received == 0) {
|
||||||
|
|
||||||
@ -618,19 +622,40 @@ int guac_rdp_print_job_write(guac_rdp_print_job* job,
|
|||||||
/* Update counter of bytes received */
|
/* Update counter of bytes received */
|
||||||
job->bytes_received += length;
|
job->bytes_received += length;
|
||||||
|
|
||||||
/* Write data to filter process */
|
/* Write data to filter process, unblocking any threads waiting on the
|
||||||
return write(job->input_fd, buffer, length);
|
* generic RDP message lock as this may be a lengthy operation that depends
|
||||||
|
* on other threads sending outstanding messages (resulting in deadlock if
|
||||||
|
* those messages are blocked) */
|
||||||
|
int unlock_status = pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
int write_status = write(job->input_fd, buffer, length);
|
||||||
|
|
||||||
|
/* Restore RDP message lock state */
|
||||||
|
if (!unlock_status)
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
|
return write_status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdp_print_job_free(guac_rdp_print_job* job) {
|
void guac_rdp_print_job_free(guac_rdp_print_job* job) {
|
||||||
|
|
||||||
|
guac_client* client = job->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* No more input will be provided */
|
/* No more input will be provided */
|
||||||
close(job->input_fd);
|
close(job->input_fd);
|
||||||
|
|
||||||
/* Wait for job to terminate */
|
/* Wait for job to terminate, unblocking any threads waiting on the generic
|
||||||
|
* RDP message lock as this may be a lengthy operation that depends on
|
||||||
|
* other threads sending outstanding messages (resulting in deadlock if
|
||||||
|
* those messages are blocked) */
|
||||||
|
int unlock_status = pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
pthread_join(job->output_thread, NULL);
|
pthread_join(job->output_thread, NULL);
|
||||||
|
|
||||||
|
/* Restore RDP message lock state */
|
||||||
|
if (!unlock_status)
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Destroy lock */
|
/* Destroy lock */
|
||||||
pthread_mutex_destroy(&(job->state_lock));
|
pthread_mutex_destroy(&(job->state_lock));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user