summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-05-02 14:19:06 +0300
committerLeif Åstrand <leif@vaadin.com>2013-05-02 14:19:06 +0300
commit79e9ddc5247ae154d5f63ceeeb02afb293dbc91f (patch)
tree549b93d0ad704e43cc7b3521254dde7640e5450a
parent80d96608dd9f2e0c067918065bfcdcfde0cb3414 (diff)
downloadvaadin-framework-79e9ddc5247ae154d5f63ceeeb02afb293dbc91f.tar.gz
vaadin-framework-79e9ddc5247ae154d5f63ceeeb02afb293dbc91f.zip
Make access() throw if another session is already locked (#11757)
Change-Id: Ic8571b0d078c3ff64e8b9914e55c51766ae49024
-rw-r--r--server/src/com/vaadin/server/VaadinService.java19
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java12
-rw-r--r--server/src/com/vaadin/ui/UI.java10
3 files changed, 41 insertions, 0 deletions
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index f6b520d4b0..083bd4bedf 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -1541,6 +1541,25 @@ public abstract class VaadinService implements Serializable {
}
/**
+ * Checks that another {@link VaadinSession} instance is not locked. This is
+ * internally used by {@link VaadinSession#access(Runnable)} and
+ * {@link UI#access(Runnable)} to help avoid causing deadlocks.
+ *
+ * @since 7.1
+ * @param session
+ * the session that is being locked
+ * @throws IllegalStateException
+ * if the current thread holds the lock for another session
+ */
+ public static void verifyNoOtherSessionLocked(VaadinSession session) {
+ VaadinSession otherSession = VaadinSession.getCurrent();
+ if (otherSession != null && otherSession != session) {
+ throw new IllegalStateException(
+ "Can't access session while another session is locked by the same thread. This restriction is intended to help avoid deadlocks.");
+ }
+ }
+
+ /**
* Verifies that the given CSRF token (aka double submit cookie) is valid
* for the given session. This is used to protect against Cross Site Request
* Forgery attacks.
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
index fe786ad52b..317ea6cf7b 100644
--- a/server/src/com/vaadin/server/VaadinSession.java
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -1075,15 +1075,27 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
* as the session is automatically locked by the framework during request
* handling.
* </p>
+ * <p>
+ * Note that calling this method while another session is locked by the
+ * current thread will cause an exception. This is to prevent deadlock
+ * situations when two threads have locked one session each and are both
+ * waiting for the lock for the other session.
+ * </p>
*
* @param runnable
* the runnable which accesses the session
*
+ * @throws IllegalStateException
+ * if the current thread holds the lock for another session
+ *
+ *
* @see #lock()
* @see #getCurrent()
* @see UI#access(Runnable)
*/
public void access(Runnable runnable) {
+ VaadinService.verifyNoOtherSessionLocked(this);
+
Map<Class<?>, CurrentInstance> old = null;
lock();
try {
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index f260a6af79..6433bebbe4 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -1103,12 +1103,20 @@ public abstract class UI extends AbstractSingleComponentContainer implements
* RPC handlers for components inside this UI do not need this method as the
* session is automatically locked by the framework during request handling.
* </p>
+ * <p>
+ * Note that calling this method while another session is locked by the
+ * current thread will cause an exception. This is to prevent deadlock
+ * situations when two threads have locked one session each and are both
+ * waiting for the lock for the other session.
+ * </p>
*
* @param runnable
* the runnable which accesses the UI
* @throws UIDetachedException
* if the UI is not attached to a session (and locking can
* therefore not be done)
+ * @throws IllegalStateException
+ * if the current thread holds the lock for another session
*
* @see #getCurrent()
* @see VaadinSession#access(Runnable)
@@ -1123,6 +1131,8 @@ public abstract class UI extends AbstractSingleComponentContainer implements
throw new UIDetachedException();
}
+ VaadinService.verifyNoOtherSessionLocked(session);
+
session.lock();
try {
if (getSession() == null) {