From 5d0b53bad905a2f77e4e75a3e307a69824c9b87d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Mon, 29 Jul 2013 15:51:33 +0300 Subject: [PATCH] Fix race condition that might leave access queue unpurged (#12292) Cherry-pick of 3a373efe (the original fix) and 2ff71f62 (fixing a regression) that were marked to not be automatically merged from 7.1 to master. Change-Id: Iee1012486906d8c2c46cef94cfcd6d2b399d7a6b --- .../src/com/vaadin/server/VaadinService.java | 19 +++++++++++++++++-- .../src/com/vaadin/server/VaadinSession.java | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index c926efc67c..86cd9701c0 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -1696,6 +1696,23 @@ public abstract class VaadinService implements Serializable { FutureAccess future = new FutureAccess(session, runnable); session.getPendingAccessQueue().add(future); + ensureAccessQueuePurged(session); + + return future; + } + + /** + * Makes sure the pending access queue is purged for the provided session. + * If the session is currently locked by the current thread or some other + * thread, the queue will be purged when the session is unlocked. If the + * lock is not held by any thread, it is acquired and the queue is purged + * right away. + * + * @since 7.1.2 + * @param session + * the session for which the access queue should be purged + */ + public void ensureAccessQueuePurged(VaadinSession session) { /* * If no thread is currently holding the lock, pending changes for UIs * with automatic push would not be processed and pushed until the next @@ -1718,8 +1735,6 @@ public abstract class VaadinService implements Serializable { } catch (InterruptedException e) { // Just ignore } - - return future; } /** diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java index 265d18b859..619a329ab9 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -969,12 +969,14 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { */ public void unlock() { assert hasLock(); + boolean ultimateRelease = false; try { /* * Run pending tasks and push if the reentrant lock will actually be * released by this unlock() invocation. */ if (((ReentrantLock) getLockInstance()).getHoldCount() == 1) { + ultimateRelease = true; getService().runPendingAccessTasks(this); for (UI ui : getUIs()) { @@ -992,6 +994,18 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable { } finally { getLockInstance().unlock(); } + + /* + * If the session is locked when a new access task is added, it is + * assumed that the queue will be purged when the lock is released. This + * might however not happen if a task is enqueued between the moment + * when unlock() purges the queue and the moment when the lock is + * actually released. This means that the queue should be purged again + * if it is not empty after unlocking. + */ + if (ultimateRelease && !getPendingAccessQueue().isEmpty()) { + getService().ensureAccessQueuePurged(this); + } } /** -- 2.39.5