libchromeos: New class to watch child processes.

This patch ports the ProcessReaper class previously used in germ to
libchromeos with a base::Callback interface. This class allows you to
wait for a child process in the message loop, similar to what the
g_child_watch_add() function does in glib. This class is compatible
with both GlibMessageLoop and BaseMessageLoop.

BUG=chromium:361635
TEST=Added unittests.

Change-Id: Ia40246729c99a487fdf0039a28b30ba92f0e7da4
Reviewed-on: https://chromium-review.googlesource.com/288259
Trybot-Ready: Alex Deymo <deymo@chromium.org>
Tested-by: Alex Deymo <deymo@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/chromeos/process_reaper.h b/chromeos/process_reaper.h
new file mode 100644
index 0000000..1e69055
--- /dev/null
+++ b/chromeos/process_reaper.h
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBCHROMEOS_CHROMEOS_PROCESS_REAPER_H_
+#define LIBCHROMEOS_CHROMEOS_PROCESS_REAPER_H_
+
+#include <sys/wait.h>
+
+#include <map>
+
+#include <base/callback.h>
+#include <base/location.h>
+#include <base/macros.h>
+#include <chromeos/asynchronous_signal_handler.h>
+#include <chromeos/daemons/daemon.h>
+
+namespace chromeos {
+
+class CHROMEOS_EXPORT ProcessReaper final {
+ public:
+  // The callback called when a child exits.
+  using ChildCallback = base::Callback<void(const siginfo_t&)>;
+
+  ProcessReaper() = default;
+  ~ProcessReaper();
+
+  // Register the ProcessReaper using either the provided chromeos::Daemon or
+  // chromeos::AsynchronousSignalHandler. You can call Unregister() to remove
+  // this ProcessReapper or it will be called during shutdown.
+  void RegisterWithAsynchronousSignalHandler(
+      AsynchronousSignalHandler* async_signal_handler);
+  void RegisterWithDaemon(Daemon* daemon);
+
+  // Unregisters the ProcessReaper from the chromeos::Daemon or
+  // chromeos::AsynchronousSignalHandler passed in RegisterWith*(). It doesn't
+  // do anything if not registered.
+  void Unregister();
+
+  // Watch for the child process |pid| to finish and call |callback| when the
+  // selected process exits or the process terminates for other reason. The
+  // |callback| receives the exit status and exit code of the terminated process
+  // as a siginfo_t. See wait(2) for details about siginfo_t.
+  bool WatchForChild(const tracked_objects::Location& from_here,
+                     pid_t pid,
+                     const ChildCallback& callback);
+
+ private:
+  // SIGCHLD handler for the AsynchronousSignalHandler. Always returns false
+  // (meaning that the signal handler should not be unregistered).
+  bool HandleSIGCHLD(const signalfd_siginfo& sigfd_info);
+
+  struct WatchedProcess {
+    tracked_objects::Location location;
+    ChildCallback callback;
+  };
+  std::map<pid_t, WatchedProcess> watched_processes_;
+
+  // Whether the ProcessReaper already registered a signal.
+  bool registered_{false};
+
+  // The |async_signal_handler_| and |daemon_| are owned by the caller and only
+  // one of them is not nullptr.
+  AsynchronousSignalHandler* async_signal_handler_{nullptr};
+  Daemon* daemon_{nullptr};
+
+  DISALLOW_COPY_AND_ASSIGN(ProcessReaper);
+};
+
+}  // namespace chromeos
+
+#endif  // LIBCHROMEOS_CHROMEOS_PROCESS_REAPER_H_