|
|
Chromium Code Reviews
Description[Android] Fix race condition in BaseTestServer.
BUG=485417
Committed: https://crrev.com/1ce809f9a732b049e4c0bd7ea54d454ca48537d9
Cr-Commit-Position: refs/heads/master@{#329111}
Patch Set 1 #
Total comments: 9
Patch Set 2 : #
Total comments: 2
Patch Set 3 : rebase + fix gyp #Patch Set 4 : fix compile #Patch Set 5 : #
Messages
Total messages: 42 (15 generated)
jbudorick@chromium.org changed reviewers: + nyquist@chromium.org, rsleevi@chromium.org
In addition to partial duplication of the //net test server, https://codereview.chromium.org/869083004/ also contained a fix for a race condition in BaseTestServer. That CL didn't make it through reviews due to larger issues with my approach to the //net test server and android, but the code that triggers the race condition is still used in some scenarios (e.g. when running instrumentation tests on Appurify).
rsleevi@chromium.org changed reviewers: + ellyjones@chromium.org, mef@chromium.org
Misha or Elly: Would you be suited to do this review? It's unclear who is hacking on Java + Cronet these days, but it'd be great to get perspective of someone with Java & //net experience to review this.
Also, can you make sure there is a bug on file documenting the issues here?
On 2015/05/07 01:03:55, Ryan Sleevi wrote: > Also, can you make sure there is a bug on file documenting the issues here? done
I'll be happy to review. On Wed, May 6, 2015 at 11:44 PM, <jbudorick@chromium.org> wrote: > On 2015/05/07 01:03:55, Ryan Sleevi wrote: > >> Also, can you make sure there is a bug on file documenting the issues >> here? >> > > done > > https://codereview.chromium.org/1131803002/ > To unsubscribe from this group and stop receiving emails from it, send an email to chromium-reviews+unsubscribe@chromium.org.
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (left): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:20: mKeepRunning.set(true); Don't you need this if server is stopped and restarted? https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (right): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:26: public abstract int getServerPort(); Does it belong to this CL? If so, shouldn't there be a corresponding addition to the concrete class that inherits from BaseTestServer? https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:43: synchronized (mLock) { I don't think this works. The wait loop is inside of synchronized(mLock), so the server thread will be blocked inside of serverHasStarted().
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (left): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:20: mKeepRunning.set(true); On 2015/05/07 15:04:32, mef wrote: > Don't you need this if server is stopped and restarted? Restarting isn't supported at all at the moment since Threads can't be started more than once. If it were, then yes. https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (right): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:26: public abstract int getServerPort(); On 2015/05/07 15:04:32, mef wrote: > Does it belong to this CL? > > If so, shouldn't there be a corresponding addition to the concrete class that > inherits from BaseTestServer? Nope, this is a renegade from the other CL. Removed. https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:43: synchronized (mLock) { On 2015/05/07 15:04:32, mef wrote: > I don't think this works. The wait loop is inside of synchronized(mLock), so the > server thread will be blocked inside of serverHasStarted(). This definitely works. wait() doesn't hold the monitor while waiting to be notified.
Hrm, maybe I'm missing something, doesn't synchronized(object) {} hold an
exclusive lock on the object?
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/...
File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java
(right):
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/...
net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:43:
synchronized (mLock) {
On 2015/05/07 15:41:17, jbudorick wrote:
> On 2015/05/07 15:04:32, mef wrote:
> > I don't think this works. The wait loop is inside of synchronized(mLock), so
> the
> > server thread will be blocked inside of serverHasStarted().
>
> This definitely works. wait() doesn't hold the monitor while waiting to be
> notified.
Right, but while this method is waiting in the loop the mLock is locked by
synchronized block.
https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate...
File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java
(right):
https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate...
net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:52:
synchronized (mLock) {
If this method is called after waitForServerToStart(), then this will be waiting
for the lock held in waitForServerToStart().
On 2015/05/07 15:59:56, mef wrote:
> Hrm, maybe I'm missing something, doesn't synchronized(object) {} hold an
> exclusive lock on the object?
synchronized (object) {} will grab the object's monitor (~ object lock). Waiting
on an object while holding its monitor (which is a precondition for waiting on
an object:
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait()) will
release the monitor, wait for a notification on the monitor, then reacquire the
monitor before continuing.
>
>
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/...
> File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java
> (right):
>
>
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/...
> net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:43:
> synchronized (mLock) {
> On 2015/05/07 15:41:17, jbudorick wrote:
> > On 2015/05/07 15:04:32, mef wrote:
> > > I don't think this works. The wait loop is inside of synchronized(mLock),
so
> > the
> > > server thread will be blocked inside of serverHasStarted().
> >
> > This definitely works. wait() doesn't hold the monitor while waiting to be
> > notified.
>
> Right, but while this method is waiting in the loop the mLock is locked by
> synchronized block.
>
>
https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate...
> File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java
> (right):
>
>
https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate...
> net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:52:
> synchronized (mLock) {
> If this method is called after waitForServerToStart(), then this will be
waiting
> for the lock held in waitForServerToStart().
In this scenario:
1. waitForServerToStart is called. It acquires mLock's monitor on entering the
synchronized block.
2. serverHasStarted is called. It is initially unable to acquire mLock's
monitor, so it's blocked at the entry to the synchronzied block.
3. waitForServerToStart calls mLock.wait(), releasing mLock's monitor and
waiting for a notify() or notifyAll() call on mLock.
4. serverHasStarted now acquires mLock's monitor and enters the synchronized
block.
5. serverHasStarted sets mRunning to true.
6. serverHasStarted calls mLock.notifyAll(). waitForServerToStart is notified
and starts trying to reacquire mLock's monitor. It is initially unable to do so
because serverHasStarted still holds the monitor.
7. serverHasStarted exits the synchronized block, releasing mLock's monitor.
8. waitForServerToStart reacquires the monitor and mLock.wait() returns.
9. waitForServerToStart sees that mRunning has been set to true and completes.
Ah, I've missed the part that wait() releases the lock. Thanks for the explanation, LGTM.
https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (right): https://codereview.chromium.org/1131803002/diff/20001/net/test/android/javate... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:52: synchronized (mLock) { On 2015/05/07 15:59:56, mef wrote: > If this method is called after waitForServerToStart(), then this will be waiting > for the lock held in waitForServerToStart(). When wait is invoked, the thread releases the lock and suspends execution. The part inside synchronized(THIS_OBJECT) must match the THIS_OBJECT.wait() and THIS_OBJECT.notify() for this to work correctly. See http://developer.android.com/reference/java/lang/Object.html#wait() or See https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html for some more helpful concurrency documentation.
Tommy, can you do an owners review for chrome/test/android/?
chrome/test/android lgtm
The CQ bit was checked by jbudorick@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/20001
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: android_arm64_dbg_recipe on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/android_arm64_d...) android_clang_dbg_recipe on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/android_clang_d...) android_compile_dbg on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/android_compile...) cast_shell_android on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/cast_shell_andr...)
The CQ bit was checked by jbudorick@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from nyquist@chromium.org, mef@chromium.org Link to the patchset: https://codereview.chromium.org/1131803002/#ps40001 (title: "rebase + fix gyp")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/40001
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: linux_android_rel_ng on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/linux_android_r...)
https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (left): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:31: public abstract int getServerPort(); (moved from here) https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... File net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java (right): https://codereview.chromium.org/1131803002/diff/1/net/test/android/javatests/... net/test/android/javatests/src/org/chromium/net/test/BaseTestServer.java:26: public abstract int getServerPort(); On 2015/05/07 15:41:17, jbudorick wrote: > On 2015/05/07 15:04:32, mef wrote: > > Does it belong to this CL? > > > > If so, shouldn't there be a corresponding addition to the concrete class that > > inherits from BaseTestServer? > > Nope, this is a renegade from the other CL. Removed. Turns out this isn't a renegade, it just moved up from below. Deleting it causes problems, unsurprisingly.
The CQ bit was checked by jbudorick@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from nyquist@chromium.org, mef@chromium.org Link to the patchset: https://codereview.chromium.org/1131803002/#ps80001 (title: " ")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/80001
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: mac_chromium_rel_ng on tryserver.chromium.mac (JOB_TIMED_OUT, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_...)
The CQ bit was checked by nyquist@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/80001
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: chromium_presubmit on tryserver.chromium.linux (JOB_TIMED_OUT, no build URL)
The CQ bit was checked by jbudorick@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/80001
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: chromium_presubmit on tryserver.chromium.linux (JOB_TIMED_OUT, no build URL)
The CQ bit was checked by jbudorick@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1131803002/80001
Message was sent while issue was closed.
Committed patchset #5 (id:80001)
Message was sent while issue was closed.
Patchset 5 (id:??) landed as https://crrev.com/1ce809f9a732b049e4c0bd7ea54d454ca48537d9 Cr-Commit-Position: refs/heads/master@{#329111} |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
