1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef LIBBRILLO_BRILLO_PROCESS_REAPER_H_
6 #define LIBBRILLO_BRILLO_PROCESS_REAPER_H_
7 
8 #include <sys/wait.h>
9 
10 #include <map>
11 
12 #include <base/callback.h>
13 #include <base/location.h>
14 #include <base/macros.h>
15 #include <brillo/asynchronous_signal_handler.h>
16 
17 namespace brillo {
18 
19 class BRILLO_EXPORT ProcessReaper final {
20  public:
21   // The callback called when a child exits.
22   using ChildCallback = base::Callback<void(const siginfo_t&)>;
23 
24   ProcessReaper() = default;
25   ~ProcessReaper();
26 
27   // Register the ProcessReaper using either the provided
28   // brillo::AsynchronousSignalHandlerInterface. You can call Unregister() to
29   // remove this ProcessReapper or it will be called during shutdown.
30   // You can only register this ProcessReaper with one signal handler at a time.
31   void Register(AsynchronousSignalHandlerInterface* async_signal_handler);
32 
33   // Unregisters the ProcessReaper from the
34   // brillo::AsynchronousSignalHandlerInterface passed in Register(). It
35   // doesn't do anything if not registered.
36   void Unregister();
37 
38   // Watch for the child process |pid| to finish and call |callback| when the
39   // selected process exits or the process terminates for other reason. The
40   // |callback| receives the exit status and exit code of the terminated process
41   // as a siginfo_t. See wait(2) for details about siginfo_t.
42   bool WatchForChild(const base::Location& from_here,
43                      pid_t pid,
44                      const ChildCallback& callback);
45 
46   // Stop watching child process |pid|.  This is useful in situations
47   // where the child process may have been reaped outside of the signal
48   // handler, or the caller is no longer interested in being notified about
49   // this child process anymore.  Returns true if a child was removed from
50   // the watchlist.
51   bool ForgetChild(pid_t pid);
52 
53  private:
54   // SIGCHLD handler for the AsynchronousSignalHandler. Always returns false
55   // (meaning that the signal handler should not be unregistered).
56   bool HandleSIGCHLD(const signalfd_siginfo& sigfd_info);
57 
58   struct WatchedProcess {
59     base::Location location;
60     ChildCallback callback;
61   };
62   std::map<pid_t, WatchedProcess> watched_processes_;
63 
64   // The |async_signal_handler_| is owned by the caller and is |nullptr| when
65   // not registered.
66   AsynchronousSignalHandlerInterface* async_signal_handler_{nullptr};
67 
68   DISALLOW_COPY_AND_ASSIGN(ProcessReaper);
69 };
70 
71 }  // namespace brillo
72 
73 #endif  // LIBBRILLO_BRILLO_PROCESS_REAPER_H_
74