From e776fbfcec2a7d6fbbb234c2746ff8c9ecf0fd62 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 10 Jan 2012 23:06:28 -0800 Subject: [PATCH] Fix race condition where the source of a copy operation may be altered before the destination is drawn to (thus the copy may not always copy what we THINK it should be copying, especially if many buffers are repeatedly used and quickly discarded). --- .../src/main/resources/layer.js | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/guacamole-common-js/src/main/resources/layer.js b/guacamole-common-js/src/main/resources/layer.js index e76206045..6885f59e6 100644 --- a/guacamole-common-js/src/main/resources/layer.js +++ b/guacamole-common-js/src/main/resources/layer.js @@ -372,7 +372,7 @@ Guacamole.Layer = function(width, height) { * pending operations are complete. */ this.sync = function(handler) { - scheduleTask(handler); + return scheduleTask(handler); }; /** @@ -398,12 +398,18 @@ Guacamole.Layer = function(width, height) { */ this.copyRect = function(srcLayer, srcx, srcy, srcw, srch, x, y) { + var srcCopied = null; + function doCopyRect() { if (layer.autosize != 0) fitRect(x, y, srcw, srch); var srcCanvas = srcLayer.getCanvas(); if (srcCanvas.width != 0 && srcCanvas.height != 0) displayContext.drawImage(srcCanvas, srcx, srcy, srcw, srch, x, y, srcw, srch); + + // Unblock the copy complete task, if it exists + if (srcCopied != null) + srcCopied.handler = function() {}; } // If we ARE the source layer, no need to sync. @@ -413,8 +419,13 @@ Guacamole.Layer = function(width, height) { // Otherwise synchronize copy operation with source layer else { + + // Task which will be unblocked only when the source layer is ready + // This task will perform the copy var task = scheduleTask(null); - srcLayer.sync(function() { + + // Task which will unblock the drawing task. + var srcReady = srcLayer.sync(function() { task.handler = doCopyRect; @@ -423,6 +434,13 @@ Guacamole.Layer = function(width, height) { handlePendingTasks(); }); + + // Task which will be unblocked only after the copy has + // occurred (this will only be created if the draw task + // was postponed) + if (srcReady != null) + srcCopied = srcLayer.sync(null); + } };