Bug 931456 - Check whether b2g and its descendant have opened files only. r=dhylands
authorAlan Huang <ahuang@mozilla.com>
Tue, 03 Dec 2013 15:35:03 +0800
changeset 174244 68a34c25a2ab9048d0a4868a7d21bf068ff9e218
parent 174243 0e1a6c3f57698cccb1698caee839d3c90de36f43
child 174245 3f4fa4816a6e8d7b5ff82ee2ae91b3164bb00baf
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdhylands
bugs931456
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 931456 - Check whether b2g and its descendant have opened files only. r=dhylands
dom/system/gonk/OpenFileFinder.cpp
dom/system/gonk/OpenFileFinder.h
--- a/dom/system/gonk/OpenFileFinder.cpp
+++ b/dom/system/gonk/OpenFileFinder.cpp
@@ -8,21 +8,24 @@
 #include "nsPrintfCString.h"
 
 #include <sys/stat.h>
 #include <errno.h>
 
 namespace mozilla {
 namespace system {
 
-OpenFileFinder::OpenFileFinder(const nsACString& aPath)
+OpenFileFinder::OpenFileFinder(const nsACString& aPath,
+                               bool aCheckIsB2gOrDescendant /* = true */)
   : mPath(aPath),
     mProcDir(nullptr),
     mFdDir(nullptr),
-    mPid(0)
+    mPid(0),
+    mMyPid(-1),
+    mCheckIsB2gOrDescendant(aCheckIsB2gOrDescendant)
 {
 }
 
 OpenFileFinder::~OpenFileFinder()
 {
   Close();
 }
 
@@ -81,17 +84,24 @@ OpenFileFinder::Next(OpenFileFinder::Inf
             continue;
           }
           nsPrintfCString fdSymLink("/proc/%d/fd/%s", mPid, fdEntry->d_name);
           nsCString resolvedPath;
           if (ReadSymLink(fdSymLink, resolvedPath) && PathMatches(resolvedPath)) {
             // We found an open file contained within the directory tree passed
             // into the constructor.
             FillInfo(aInfo, resolvedPath);
-            return true;
+            // If sCheckIsB2gOrDescendant is set false, the caller cares about
+            // all processes which have open files. If sCheckIsB2gOrDescendant
+            // is set false, we only care about the b2g proccess or its descendants.
+            if (!mCheckIsB2gOrDescendant || aInfo->mIsB2gOrDescendant) {
+              return true;
+            }
+            LOG("Ignore process(%d), not a b2g process or its descendant.",
+                aInfo->mPid);
           }
         }
         // We've checked all of the files for this pid, move onto the next one.
         mState = NEXT_PID;
         continue;
       }
       case DONE:
       default:
@@ -148,19 +158,51 @@ OpenFileFinder::FillInfo(OpenFileFinder:
   nsDependentCSubstring comm(&openParen[1], closeParen - openParen - 1);
   aInfo->mComm = comm;
   // There is a single character field after the comm and then
   // the parent pid (the field we're interested in).
   // ) X ppid
   // 01234
   int ppid = atoi(&closeParen[4]);
   // We assume that we're running in the parent process
-  if (ppid != getpid()) {
+  if (mMyPid == -1) {
+    mMyPid = getpid();
+  }
+
+  if (mPid == mMyPid) {
+    // This is chrome process
+    aInfo->mIsB2gOrDescendant = true;
+    DBG("Chrome process has open file(s)");
     return;
   }
+  // For the rest (non-chrome process), we recursively check the ppid to know
+  // it is a descendant of b2g or not. See bug 931456.
+  while (ppid != mMyPid && ppid != 1) {
+    DBG("Process(%d) is not forked from b2g(%d) or Init(1), keep looking",
+        ppid, mMyPid);
+    nsPrintfCString ppStatPath("/proc/%d/stat", ppid);
+    ReadSysFile(ppStatPath.get(), stat, statString.Length());
+    closeParen = strrchr(stat, ')');
+    if (!closeParen) {
+      return;
+    }
+    ppid = atoi(&closeParen[4]);
+  }
+  if (ppid == 1) {
+    // This is a not a b2g process.
+    DBG("Non-b2g process has open file(s)");
+    aInfo->mIsB2gOrDescendant = false;
+    return;
+  }
+  if (ppid == mMyPid) {
+    // This is a descendant of b2g.
+    DBG("Child process of chrome process has open file(s)");
+    aInfo->mIsB2gOrDescendant = true;
+  }
+
   // This looks like a content process. The comm field will be the
   // app name.
   aInfo->mAppName = aInfo->mComm;
 }
 
 bool
 OpenFileFinder::ReadSymLink(const nsACString& aSymLink, nsACString& aOutPath)
 {
--- a/dom/system/gonk/OpenFileFinder.h
+++ b/dom/system/gonk/OpenFileFinder.h
@@ -4,16 +4,29 @@
 
 #ifndef mozilla_system_openfilefinder_h__
 #define mozilla_system_openfilefinder_h__
 
 #include "nsString.h"
 
 #include <dirent.h>
 
+#define USE_DEBUG 0
+
+#undef LOG
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO,  "OpenFileFinder", ## args)
+#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN,  "OpenFileFinder", ## args)
+#define ERR(args...)  __android_log_print(ANDROID_LOG_ERROR, "OpenFileFinder", ## args)
+
+#if USE_DEBUG
+#define DBG(args...)  __android_log_print(ANDROID_LOG_DEBUG, "OpenFileFinder" , ## args)
+#else
+#define DBG(args...)
+#endif
+
 namespace mozilla {
 namespace system {
 
 class OpenFileFinder
 {
 public:
   enum State
   {
@@ -24,19 +37,20 @@ public:
   class Info
   {
   public:
     nsCString mFileName;  // name of the the open file
     nsCString mAppName;   // App which has the file open (if it's a b2g app)
     pid_t     mPid;       // pid of the process which has the file open
     nsCString mComm;      // comm associated with pid
     nsCString mExe;       // executable name associated with pid
+    bool      mIsB2gOrDescendant; // this is b2g/its descendant or not
   };
 
-  OpenFileFinder(const nsACString& aPath);
+  OpenFileFinder(const nsACString& aPath, bool aCheckIsB2gOrDescendant = true);
   ~OpenFileFinder();
 
   bool First(Info* aInfo);  // Return the first open file
   bool Next(Info* aInfo);   // Return the next open file
   void Close();
 
 private:
 
@@ -47,14 +61,16 @@ private:
     return Substring(aPath, 0, mPath.Length()).Equals(mPath);
   }
 
   State     mState;   // Keeps track of what we're doing.
   nsCString mPath;    // Only report files contained within this directory tree
   DIR*      mProcDir; // Used for scanning /proc
   DIR*      mFdDir;   // Used for scanning /proc/PID/fd
   int       mPid;     // PID currently being processed
+  pid_t     mMyPid;   // PID of parent process, we assume we're running on it.
+  bool      mCheckIsB2gOrDescendant; // Do we care about non-b2g process?
 };
 
 } // system
 } // mozilla
 
 #endif  // mozilla_system_nsvolume_h__