diff options
author | Daniel Sievers <sievers@chromium.org> | 2015-04-06 19:01:43 -0700 |
---|---|---|
committer | Daniel Sievers <sievers@chromium.org> | 2015-04-07 02:07:04 +0000 |
commit | 4d95abadb6d081349c9d4e3ffb0036c575e92567 (patch) | |
tree | 19e939680ba34f127c0180bf27a901ec901807c3 | |
parent | 22aef40b26744fa0e70b1fe822b3dfd4d75a67b8 (diff) | |
download | chromium_src-4d95abadb6d081349c9d4e3ffb0036c575e92567.zip chromium_src-4d95abadb6d081349c9d4e3ffb0036c575e92567.tar.gz chromium_src-4d95abadb6d081349c9d4e3ffb0036c575e92567.tar.bz2 |
Fix deadlock in ChildProcessService.onDestroy()
onCreate() spawns the CrMain thread. onDestroy() can happen quickly
after onCreate() (for example if the browser crashes),
so we have to be careful about blocking on any semaphores
wrt the CrMain thread.
The existing cmdline check did not cover all of that.
In addition we have to avoid deadlocks between
nativeShutdownMainThread()and us actually not having ever
entered native main().
(ChildThreadImpl::Shutdown() on Android waits on a
condition variable.)
BUG=448549,457406,457914
NOTRY=True
Review URL: https://codereview.chromium.org/1052133002
Cr-Commit-Position: refs/heads/master@{#323567}
Review URL: https://codereview.chromium.org/1061133004
Cr-Commit-Position: refs/branch-heads/2311@{#441}
Cr-Branched-From: 09b7de5dd7254947cd4306de907274fa63373d48-refs/heads/master@{#317474}
-rw-r--r-- | content/public/android/java/src/org/chromium/content/app/ChildProcessService.java | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java index 5c91035..fae9a41 100644 --- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java @@ -31,6 +31,7 @@ import org.chromium.content.common.IChildProcessCallback; import org.chromium.content.common.IChildProcessService; import java.util.ArrayList; +import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicReference; /** @@ -66,6 +67,8 @@ public class ChildProcessService extends Service { // Becomes true once the service is bound. Access must synchronize around mMainThread. private boolean mIsBound = false; + private final Semaphore mActivitySemaphore = new Semaphore(1); + // Binder object used by clients for this service. private final IChildProcessService.Stub mBinder = new IChildProcessService.Stub() { // NOTE: Implement any IChildProcessService methods here. @@ -213,8 +216,10 @@ public class ChildProcessService extends Service { nativeInitChildProcess(sContext.get().getApplicationContext(), ChildProcessService.this, fileIds, fileFds, mCpuCount, mCpuFeatures); - ContentMain.start(); - nativeExitChildProcess(); + if (mActivitySemaphore.tryAcquire()) { + ContentMain.start(); + nativeExitChildProcess(); + } } catch (InterruptedException e) { Log.w(TAG, MAIN_THREAD_NAME + " startup failed: " + e); } catch (ProcessInitException e) { @@ -226,11 +231,16 @@ public class ChildProcessService extends Service { } @Override + @SuppressFBWarnings("DM_EXIT") public void onDestroy() { Log.i(TAG, "Destroying ChildProcessService pid=" + Process.myPid()); super.onDestroy(); - if (mCommandLineParams == null) { - // This process was destroyed before it even started. Nothing more to do. + if (mActivitySemaphore.tryAcquire()) { + // TODO(crbug.com/457406): This is a bit hacky, but there is no known better solution + // as this service will get reused (at least if not sandboxed). + // In fact, we might really want to always exit() from onDestroy(), not just from + // the early return here. + System.exit(0); return; } synchronized (mMainThread) { |