From: Leif Åstrand Date: Mon, 29 Jul 2013 12:51:33 +0000 (+0300) Subject: Fix race condition that might leave access queue unpurged (#12277) X-Git-Tag: 7.1.2~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3a373efe;p=vaadin-framework.git Fix race condition that might leave access queue unpurged (#12277) Merge: no Change-Id: Iee1012486906d8c2c46cef94cfcd6d2b399d7a6b --- diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java index f603fbd1e9..17bce7ad15 100644 --- a/server/src/com/vaadin/server/VaadinService.java +++ b/server/src/com/vaadin/server/VaadinService.java @@ -1655,6 +1655,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 @@ -1677,8 +1694,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 8f27241384..8de01e22bc 100644 --- a/server/src/com/vaadin/server/VaadinSession.java +++ b/server/src/com/vaadin/server/VaadinSession.java @@ -926,6 +926,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 (!getPendingAccessQueue().isEmpty()) { + getService().ensureAccessQueuePurged(this); + } } /**