crash-reporter: Validate proc files and log the state of crashed process.

This CL makes the following changes to UserCollector:
1. Check if the maps file is empty after copying proc files to the
   temporary container directory, which prevents the core-to-minidump
   conversion failure due to unusable maps file.
2. Obtain and log the state of the crashed process, which helps
   determine if the crashed process is in the zombie state.
3. Refactor the status file processing code.

BUG=chromium-os:24820
TEST=Tested the following:
1. Build crash-reporter and run unit tests.
2. Run the following autotest tests on a Cr48:
   - logging_CrashSender
   - logging_UserCrash
3. Check that the process state of a crashed process is logged in
   /var/log/messages.

Change-Id: Iebaf9c36c18185c703c18e7028ee4673dd9ebc93
Reviewed-on: https://gerrit.chromium.org/gerrit/13826
Reviewed-by: Ken Mixter <kmixter@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
Commit-Ready: Ben Chan <benchan@chromium.org>
diff --git a/crash_reporter/user_collector.h b/crash_reporter/user_collector.h
index d041628..043d38c 100644
--- a/crash_reporter/user_collector.h
+++ b/crash_reporter/user_collector.h
@@ -58,7 +58,9 @@
   FRIEND_TEST(UserCollectorTest, CopyOffProcFilesBadPid);
   FRIEND_TEST(UserCollectorTest, CopyOffProcFilesOK);
   FRIEND_TEST(UserCollectorTest, GetExecutableBaseNameFromPid);
+  FRIEND_TEST(UserCollectorTest, GetFirstLineWithPrefix);
   FRIEND_TEST(UserCollectorTest, GetIdFromStatus);
+  FRIEND_TEST(UserCollectorTest, GetStateFromStatus);
   FRIEND_TEST(UserCollectorTest, GetProcessPath);
   FRIEND_TEST(UserCollectorTest, GetSymlinkTarget);
   FRIEND_TEST(UserCollectorTest, GetUserInfoFromName);
@@ -66,6 +68,7 @@
   FRIEND_TEST(UserCollectorTest, ShouldDumpChromeOverridesDeveloperImage);
   FRIEND_TEST(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent);
   FRIEND_TEST(UserCollectorTest, ShouldDumpUseConsentProductionImage);
+  FRIEND_TEST(UserCollectorTest, ValidateProcFiles);
 
   // Enumeration to pass to GetIdFromStatus.  Must match the order
   // that the kernel lists IDs in the status file.
@@ -87,15 +90,37 @@
                         FilePath *target);
   bool GetExecutableBaseNameFromPid(uid_t pid,
                                     std::string *base_name);
+  // Returns, via |line|, the first line in |lines| that starts with |prefix|.
+  // Returns true if a line is found, or false otherwise.
+  bool GetFirstLineWithPrefix(const std::vector<std::string> &lines,
+                              const char *prefix, std::string *line);
+
+  // Returns the identifier of |kind|, via |id|, found in |status_lines| on
+  // the line starting with |prefix|. |status_lines| contains the lines in
+  // the status file. Returns true if the identifier can be determined.
   bool GetIdFromStatus(const char *prefix,
                        IdKind kind,
-                       const std::string &status_contents,
+                       const std::vector<std::string> &status_lines,
                        int *id);
 
+  // Returns the process state, via |state|, found in |status_lines|, which
+  // contains the lines in the status file. Returns true if the process state
+  // can be determined.
+  bool GetStateFromStatus(const std::vector<std::string> &status_lines,
+                          std::string *state);
+
   void LogCollectionError(const std::string &error_message);
   void EnqueueCollectionErrorLog(pid_t pid, const std::string &exec_name);
 
-  bool CopyOffProcFiles(pid_t pid, const FilePath &process_map);
+  bool CopyOffProcFiles(pid_t pid, const FilePath &container_dir);
+
+  // Validates the proc files at |container_dir| and returns true if they
+  // are usable for the core-to-minidump conversion later. For instance, if
+  // a process is reaped by the kernel before the copying of its proc files
+  // takes place, some proc files like /proc/<pid>/maps may contain nothing
+  // and thus become unusable.
+  bool ValidateProcFiles(const FilePath &container_dir);
+
   // Determines the crash directory for given pid based on pid's owner,
   // and creates the directory if necessary with appropriate permissions.
   // Returns true whether or not directory needed to be created, false on