summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2016-02-14 12:17:10 +0200
committerLeif Åstrand <leif@vaadin.com>2016-02-14 13:08:59 +0200
commit493e5d7f460cf6c41b858ac6e0abafe177f4a71c (patch)
treea5cb03dc96641f9507b3e9a8f17380ccc44fd08b
parent0225d0949b566dd6913aef44840cd9ae6c399c28 (diff)
downloadvaadin-framework-493e5d7f460cf6c41b858ac6e0abafe177f4a71c.tar.gz
vaadin-framework-493e5d7f460cf6c41b858ac6e0abafe177f4a71c.zip
Lock session during deserialization (#19310)
Change-Id: I0f0c029d6de88b74bae1c7253b7665d5570e3767
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java21
-rw-r--r--server/tests/src/com/vaadin/server/VaadinSessionTest.java44
2 files changed, 55 insertions, 10 deletions
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
index bcc07acb99..304dd4bec6 100644
--- a/server/src/com/vaadin/server/VaadinSession.java
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -18,6 +18,7 @@ package com.vaadin.server;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
@@ -1420,6 +1421,26 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
}
/**
+ * Override default serialization logic to avoid
+ * ConcurrentModificationException if the contents are modified while
+ * serialization is reading them.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ Lock lock = this.lock;
+
+ if (lock != null) {
+ lock.lock();
+ }
+ try {
+ out.defaultWriteObject();
+ } finally {
+ if (lock != null) {
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
* Finds the UI with the corresponding embed id.
*
* @since 7.2
diff --git a/server/tests/src/com/vaadin/server/VaadinSessionTest.java b/server/tests/src/com/vaadin/server/VaadinSessionTest.java
index 0e50abecff..85c37d156c 100644
--- a/server/tests/src/com/vaadin/server/VaadinSessionTest.java
+++ b/server/tests/src/com/vaadin/server/VaadinSessionTest.java
@@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
@@ -42,17 +43,17 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
-public class VaadinSessionTest {
+public class VaadinSessionTest implements Serializable {
- private VaadinSession session;
- private VaadinServlet mockServlet;
- private VaadinServletService mockService;
- private ServletConfig mockServletConfig;
- private HttpSession mockHttpSession;
- private WrappedSession mockWrappedSession;
- private VaadinServletRequest vaadinRequest;
- private UI ui;
- private Lock httpSessionLock;
+ private transient VaadinSession session;
+ private transient VaadinServlet mockServlet;
+ private transient VaadinServletService mockService;
+ private transient ServletConfig mockServletConfig;
+ private transient HttpSession mockHttpSession;
+ private transient WrappedSession mockWrappedSession;
+ private transient VaadinServletRequest vaadinRequest;
+ private transient UI ui;
+ private transient Lock httpSessionLock;
@Before
public void setup() throws Exception {
@@ -316,4 +317,27 @@ public class VaadinSessionTest {
deserializedSession, deserializedLabel.session);
deserializedSession.unlock();
}
+
+ @Test
+ public void lockedDuringSerialization() throws IOException {
+ final AtomicBoolean lockChecked = new AtomicBoolean(false);
+
+ ui.setContent(new Label() {
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ Assert.assertTrue(session.hasLock());
+ lockChecked.set(true);
+ out.defaultWriteObject();
+ }
+ });
+
+ session.unlock();
+ Assert.assertFalse(session.hasLock());
+
+ ObjectOutputStream out = new ObjectOutputStream(
+ new ByteArrayOutputStream());
+ out.writeObject(session);
+
+ Assert.assertFalse(session.hasLock());
+ Assert.assertTrue(lockChecked.get());
+ }
}