ActivityManagerService native crash处理流程
2017-03-06 17:51
232 查看
在@AMS中会注册接收native crash的监听器, 以便在native进程crash时清理恢复app的生命周期等事项。
开机AMS在启动时注册监听:
NativeCrashListener 线程开始不断监听debugger的socket:/data/system/ndebugsocket
有从debuggerd收到socket数据时,处理crash数据:
新开thread处理crash具体数据,让AMS作对应处理:
@AMS处理,
native 部分:
开机启动时会开启debuggerd监控进程接收native进程异常信号量,如SIGSTOP,SIGABRT,SIGSEGV等,native处理完成后,即会往上面AMS里介绍的final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH)这个socket通知,native详细流程可以参考,
http://www.2cto.com/kf/201408/323895.html
开机AMS在启动时注册监听:
mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } ... public void startObservingNativeCrashes() { final NativeCrashListener ncl = new NativeCrashListener(this); ncl.start(); }
NativeCrashListener 线程开始不断监听debugger的socket:/data/system/ndebugsocket
// Must match the path defined in debuggerd.c.-->tombstones.cpp static final String DEBUGGERD_SOCKET_PATH = "/data/system/ndebugsocket"; final class NativeCrashListener extends Thread: public void run() { final byte[] ackSignal = new byte[1]; if (DEBUG) Slog.i(TAG, "Starting up"); // The file system entity for this socket is created with 0700 perms, owned // by system:system. debuggerd runs as root, so is capable of connecting to // it, but 3rd party apps cannot. { File socketFile = new File(DEBUGGERD_SOCKET_PATH); if (socketFile.exists()) { socketFile.delete(); } } try { FileDescriptor serverFd = Os.socket(AF_UNIX, SOCK_STREAM, 0); final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH); Os.bind(serverFd, sockAddr, 0); Os.listen(serverFd, 1); while (true) { InetSocketAddress peer = new InetSocketAddress(); FileDescriptor peerFd = null; try { if (MORE_DEBUG) Slog.v(TAG, "Waiting for debuggerd connection"); peerFd = Os.accept(serverFd, peer); if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd); if (peerFd != null) { // Only the superuser is allowed to talk to us over this socket StructUcred credentials = Os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED); if (credentials.uid == 0) { // the reporting thread may take responsibility for // acking the debugger; make sure we play along. consumeNativeCrashData(peerFd); } } } catch (Exception e) { Slog.w(TAG, "Error handling connection", e); } finally { // Always ack debuggerd's connection to us. The actual // byte written is irrelevant. if (peerFd != null) { try { Os.write(peerFd, ackSignal, 0, 1); } catch (Exception e) { /* we don't care about failures here */ if (MORE_DEBUG) { Slog.d(TAG, "Exception writing ack: " + e.getMessage()); } } try { Os.close(peerFd); } catch (ErrnoException e) { if (MORE_DEBUG) { Slog.d(TAG, "Exception closing socket: " + e.getMessage()); } } } } } } catch (Exception e) { Slog.e(TAG, "Unable to init native debug socket!", e); } }
有从debuggerd收到socket数据时,处理crash数据:
// Read the crash report from the debuggerd connection void consumeNativeCrashData(FileDescriptor fd) { if (MORE_DEBUG) Slog.i(TAG, "debuggerd connected"); final byte[] buf = new byte[4096]; final ByteArrayOutputStream os = new ByteArrayOutputStream(4096); try { StructTimeval timeout = StructTimeval.fromMillis(SOCKET_TIMEOUT_MILLIS); Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout); Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout); // first, the pid and signal number int headerBytes = readExactly(fd, buf, 0, 8); if (headerBytes != 8) { // protocol failure; give up Slog.e(TAG, "Unable to read from debuggerd"); return; } int pid = unpackInt(buf, 0); int signal = unpackInt(buf, 4); if (DEBUG) { Slog.v(TAG, "Read pid=" + pid + " signal=" + signal); } // now the text of the dump if (pid > 0) { final ProcessRecord pr; synchronized (mAm.mPidsSelfLocked) { pr = mAm.mPidsSelfLocked.get(pid); } if (pr != null) { // Don't attempt crash reporting for persistent apps if (pr.persistent) { if (DEBUG) { Slog.v(TAG, "Skipping report for persistent app " + pr); } return; } int bytes; do { // get some data bytes = Os.read(fd, buf, 0, buf.length); if (bytes > 0) { if (MORE_DEBUG) { String s = new String(buf, 0, bytes, "UTF-8"); Slog.v(TAG, "READ=" + bytes + "> " + s); } // did we just get the EOD null byte? if (buf[bytes-1] == 0) { os.write(buf, 0, bytes-1); // exclude the EOD token break; } // no EOD, so collect it and read more os.write(buf, 0, bytes); } } while (bytes > 0); // Okay, we've got the report. if (DEBUG) Slog.v(TAG, "processing"); // Mark the process record as being a native crash so that the // cleanup mechanism knows we're still submitting the report // even though the process will vanish as soon as we let // debuggerd proceed. synchronized (mAm) { pr.crashing = true; pr.forceCrashReport = true; } // Crash reporting is synchronous but we want to let debuggerd // go about it business right away, so we spin off the actual // reporting logic on a thread and let it take it's time. final String reportString = new String(os.toByteArray(), "UTF-8"); (new NativeCrashReporter(pr, signal, reportString)).start(); } else { Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid); } } else { Slog.e(TAG, "Bogus pid!"); } } catch (Exception e) { Slog.e(TAG, "Exception dealing with report", e); // ugh, fail. }
新开thread处理crash具体数据,让AMS作对应处理:
class NativeCrashReporter extends Thread : public void run() { try { CrashInfo ci = new CrashInfo(); ci.exceptionClassName = "Native crash"; ci.exceptionMessage = Os.strsignal(mSignal); ci.throwFileName = "unknown"; ci.throwClassName = "unknown"; ci.throwMethodName = "unknown"; ci.stackTrace = mCrashReport; if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()"); mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci); if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned"); } catch (Exception e) { Slog.e(TAG, "Unable to report native crash", e); } }
@AMS处理,
/* Native crash reporting uses this inner version because it needs to be somewhat * decoupled from the AM-managed cleanup lifecycle */ void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName, ApplicationErrorReport.CrashInfo crashInfo) { EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(), UserHandle.getUserId(Binder.getCallingUid()), processName, r == null ? -1 : r.info.flags, crashInfo.exceptionClassName, crashInfo.exceptionMessage, crashInfo.throwFileName, crashInfo.throwLineNumber); addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo); crashApplication(r, crashInfo); }
native 部分:
开机启动时会开启debuggerd监控进程接收native进程异常信号量,如SIGSTOP,SIGABRT,SIGSEGV等,native处理完成后,即会往上面AMS里介绍的final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH)这个socket通知,native详细流程可以参考,
http://www.2cto.com/kf/201408/323895.html
相关文章推荐
- Android 7.0 ActivityManagerService(10) App的crash处理
- Android 7.0 ActivityManagerService(10) App的crash处理
- ActivityManagerService分析——AMS启动流程
- Android 7.0 ActivityManagerService(7) 进程管理相关流程分析(1)
- Android 7.1 ActivityManagerService 屏幕旋转流程分析 (四)
- ActivityManagerService流程总结
- Android ActivityManagerService(AMS)的启动分析 << 代码讲的比较细致,在了解主要流程后再看这篇
- Android ActivityManagerService 启动流程总结
- IActivityManager ,ActivityManagerNative,ActivityManagerService之间如何进行工作
- ActivityManagerService启动流程简析
- 从问题单处理了解ActivityManagerService
- Android 7.0 ActivityManagerService(9) 进程管理相关流程分析(3) computeOomAdjLocked
- IActivityManager ActivityManagerNative ActivityManagerService之间如何进行工作
- Android7.1.1 ActivityManagerService初始化流程
- ActivityManager、ActivityManagerService、ActivityManagerNative、ActivityManagerProxy的关系(and5.1)
- PowerManagerService开机启动关于WackLock处理的相关流程
- Activity manager service :activity 启动流程中process的切换过程
- Android 7.0 ActivityManagerService(8) 进程管理相关流程分析(2) updateOomAdjLocked
- android7.0 ActivityManagerService(AMS)启动流程
- Android7.1.1 ActivityManagerService初始化流程