From ce92b0d070c4967914698b4e257c203d7121c972 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 30 Sep 2014 11:28:18 -0700 Subject: More work on issue #17656716: Unhandled exception in Window Manager Drop down the limit on when we log, since under normal operation we will never get more than a few K of data due to strict mode. Try to clean up the code paths coming in and out of binder IPCs to plug any places where we could disrupt the gather flag of a thread, causing it to keep gathering stack crawls (which is the thing that is causing our strict mode data to become so large). Change-Id: I9a46512283d33e863c429840b465855d1fabb74e --- core/java/android/app/ApplicationErrorReport.java | 2 +- core/java/android/os/Binder.java | 18 ++++++++++++++---- core/java/android/os/StrictMode.java | 9 +++++++-- core/jni/android_util_Binder.cpp | 17 ++++++----------- 4 files changed, 28 insertions(+), 18 deletions(-) (limited to 'core') diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java index be4e80e..841bd16 100644 --- a/core/java/android/app/ApplicationErrorReport.java +++ b/core/java/android/app/ApplicationErrorReport.java @@ -388,7 +388,7 @@ public class ApplicationErrorReport implements Parcelable { dest.writeInt(throwLineNumber); dest.writeString(stackTrace); int total = dest.dataPosition()-start; - if (total > 100*1024) { + if (total > 10*1024) { Slog.d("Error", "ERR: exClass=" + exceptionClassName); Slog.d("Error", "ERR: exMsg=" + exceptionMessage); Slog.d("Error", "ERR: file=" + throwFileName); diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index f5fc0d7..bbf6ed8 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -430,16 +430,18 @@ public class Binder implements IBinder { } catch (RemoteException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Binder call failed.", e); + } else { + reply.setDataPosition(0); + reply.writeException(e); } - reply.setDataPosition(0); - reply.writeException(e); res = true; } catch (RuntimeException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e); + } else { + reply.setDataPosition(0); + reply.writeException(e); } - reply.setDataPosition(0); - reply.writeException(e); res = true; } catch (OutOfMemoryError e) { // Unconditionally log this, since this is generally unrecoverable. @@ -452,6 +454,14 @@ public class Binder implements IBinder { checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); reply.recycle(); data.recycle(); + + // Just in case -- we are done with the IPC, so there should be no more strict + // mode violations that have gathered for this thread. Either they have been + // parceled and are now in transport off to the caller, or we are returning back + // to the main transaction loop to wait for another incoming transaction. Either + // way, strict mode begone! + StrictMode.clearGatheredViolations(); + return res; } } diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java index 4e9d1f0..0e561bd 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -1693,7 +1693,7 @@ public final class StrictMode { int start = p.dataPosition(); violations.get(i).writeToParcel(p, 0 /* unused flags? */); int size = p.dataPosition()-start; - if (size > 100*1024) { + if (size > 10*1024) { Slog.d(TAG, "Wrote violation #" + i + " of " + violations.size() + ": " + (p.dataPosition()-start) + " bytes"); } @@ -1725,6 +1725,11 @@ public final class StrictMode { for (int i = 0; i < numViolations; ++i) { if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i); ViolationInfo info = new ViolationInfo(p, !currentlyGathering); + if (info.crashInfo.stackTrace.length() > 5000) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.w(TAG, "Stack is getting large: " + info.crashInfo.stackTrace, here); + } info.crashInfo.stackTrace += "# via Binder call with stack:\n" + ourStack; BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); if (policy instanceof AndroidBlockGuardPolicy) { @@ -2194,7 +2199,7 @@ public final class StrictMode { dest.writeString(broadcastIntentAction); dest.writeStringArray(tags); int total = dest.dataPosition()-start; - if (total > 100*1024) { + if (total > 10*1024) { Slog.d(TAG, "VIO: policy=" + policy + " dur=" + durationMillis + " numLoop=" + violationNumThisLoop + " anim=" + numAnimationsRunning diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 2dbd382..e400698 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -264,8 +264,7 @@ protected: ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); IPCThreadState* thread_state = IPCThreadState::self(); - const int strict_policy_before = thread_state->getStrictModePolicy(); - thread_state->setLastTransactionBinderFlags(flags); + const int32_t strict_policy_before = thread_state->getStrictModePolicy(); //printf("Transact from %p to Java code sending: ", this); //data.print(); @@ -284,15 +283,11 @@ protected: env->DeleteLocalRef(excep); } - // Restore the Java binder thread's state if it changed while - // processing a call (as it would if the Parcel's header had a - // new policy mask and Parcel.enforceInterface() changed - // it...) - const int strict_policy_after = thread_state->getStrictModePolicy(); - if (strict_policy_after != strict_policy_before) { - // Our thread-local... - thread_state->setStrictModePolicy(strict_policy_before); - // And the Java-level thread-local... + // Check if the strict mode state changed while processing the + // call. The Binder state will be restored by the underlying + // Binder system in IPCThreadState, however we need to take care + // of the parallel Java state as well. + if (thread_state->getStrictModePolicy() != strict_policy_before) { set_dalvik_blockguard_policy(env, strict_policy_before); } -- cgit v1.1