Browse Source

Lock session during deserialization (#19310)

Change-Id: I0f0c029d6de88b74bae1c7253b7665d5570e3767
tags/7.7.0.alpha1
Leif Åstrand 8 years ago
parent
commit
493e5d7f46

+ 21
- 0
server/src/com/vaadin/server/VaadinSession.java View File

@@ -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;
@@ -1419,6 +1420,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.
*

+ 34
- 10
server/tests/src/com/vaadin/server/VaadinSessionTest.java View File

@@ -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());
}
}

Loading…
Cancel
Save