logd: oneline statistics does not report PID gone

- oneline, add check for gone
- Add pidGone() method, which caches the gone status

Change-Id: I8f03daeafb58583c2b08ec6b540486c05da0872d
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index f44f567..f2b9a26 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -31,6 +31,7 @@
         , mSizes(0)
         , mElements(0)
         , name(name)
+        , mGone(false)
 { }
 
 #ifdef DO_NOT_ERROR_IF_PIDSTATISTICS_USES_A_COPY_CONSTRUCTOR
@@ -41,6 +42,7 @@
         , mElementsTotal(copy->mElementsTotal)
         , mSizes(copy->mSizes)
         , mElements(copy->mElements)
+        , mGone(copy->mGone)
 { }
 #endif
 
@@ -48,6 +50,20 @@
     free(name);
 }
 
+bool PidStatistics::pidGone() {
+    if (mGone) {
+        return true;
+    }
+    if (pid == gone) {
+        return true;
+    }
+    if (kill(pid, 0) && (errno != EPERM)) {
+        mGone = true;
+        return true;
+    }
+    return false;
+}
+
 void PidStatistics::setName(char *new_name) {
     free(name);
     name = new_name;
@@ -63,7 +79,7 @@
 bool PidStatistics::subtract(unsigned short size) {
     mSizes -= size;
     --mElements;
-    return (mElements == 0) && kill(pid, 0) && (errno != EPERM);
+    return (mElements == 0) && pidGone();
 }
 
 void PidStatistics::addTotal(size_t size, size_t element) {
@@ -76,7 +92,7 @@
 // must call free to release return value
 char *PidStatistics::pidToName(pid_t pid) {
     char *retval = NULL;
-    if (pid != PidStatistics::gone) {
+    if (pid != gone) {
         char buffer[512];
         snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
         int fd = open(buffer, O_RDONLY);
@@ -659,8 +675,7 @@
                             sizes, sizesTotal);
 
             android::String8 pd("");
-            pd.appendFormat("%u%c", pid,
-                            (kill(pid, 0) && (errno != EPERM)) ? '?' : ' ');
+            pd.appendFormat("%u%c", pid, p->pidGone() ? '?' : ' ');
 
             string.appendFormat("\n%-7s%-*s %-7s%s",
                                 line ? "" : android_log_id_to_name(i),
@@ -765,14 +780,15 @@
             spaces = 0;
 
             uid_t u = up->getUid();
-            pid_t p = (*pt)->getPid();
+            PidStatistics *pp = *pt;
+            pid_t p = pp->getPid();
 
             intermediate = string.format(oneline
                                              ? ((p == PidStatistics::gone)
                                                  ? "%d/?"
-                                                 : "%d/%d")
+                                                 : "%d/%d%c")
                                              : "%d",
-                                         u, p);
+                                         u, p, pp->pidGone() ? '?' : '\0');
             string.appendFormat(first ? "\n%-12s" : "%-12s",
                                 intermediate.string());
             intermediate.clear();
@@ -809,8 +825,8 @@
             size_t gone_els = 0;
 
             for(; pt != up->end(); ++pt) {
-                PidStatistics *pp = *pt;
-                pid_t p = pp->getPid();
+                pp = *pt;
+                p = pp->getPid();
 
                 // If a PID no longer has any current logs, and is not
                 // active anymore, skip & report totals for gone.
@@ -822,7 +838,7 @@
                     continue;
                 }
                 els = pp->elements();
-                bool gone = kill(p, 0) && (errno != EPERM);
+                bool gone = pp->pidGone();
                 if (gone && (els == 0)) {
                     // ToDo: garbage collection: move this statistical bucket
                     //       from its current UID/PID to UID/? (races and