Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2015 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef SHILL_PROCESS_MANAGER_H_
     18 #define SHILL_PROCESS_MANAGER_H_
     19 
     20 #include <map>
     21 #include <string>
     22 #include <vector>
     23 
     24 #include <base/callback.h>
     25 #include <base/cancelable_callback.h>
     26 #include <base/files/file_path.h>
     27 #include <base/lazy_instance.h>
     28 #include <base/memory/weak_ptr.h>
     29 #include <base/tracked_objects.h>
     30 #include <brillo/minijail/minijail.h>
     31 #include <brillo/process.h>
     32 #include <brillo/process_reaper.h>
     33 
     34 namespace shill {
     35 
     36 class EventDispatcher;
     37 
     38 // The ProcessManager is a singleton providing process creation and
     39 // asynchronous process termination. Need to initialize it once with
     40 // Init method call.
     41 class ProcessManager {
     42  public:
     43   virtual ~ProcessManager();
     44 
     45   // This is a singleton -- use ProcessManager::GetInstance()->Foo().
     46   static ProcessManager* GetInstance();
     47 
     48   // Register async signal handler and setup process reaper.
     49   virtual void Init(EventDispatcher* dispatcher);
     50 
     51   // Call on shutdown to release async_signal_handler_.
     52   virtual void Stop();
     53 
     54   // Create and start a process for |program| with |arguments|. |enivronment|
     55   // variables will be setup in the child process before exec the |program|.
     56   // |terminate_with_parent| is used to indicate if child process should
     57   // self terminate if the parent process exits.  |exit_callback| will be
     58   // invoked when child process exits (not terminated by us).  Return -1
     59   // if failed to start the process, otherwise, return the pid of the child
     60   // process.
     61   virtual pid_t StartProcess(
     62       const tracked_objects::Location& spawn_source,
     63       const base::FilePath& program,
     64       const std::vector<std::string>& arguments,
     65       const std::map<std::string, std::string>& environment,
     66       bool terminate_with_parent,
     67       const base::Callback<void(int)>& exit_callback);
     68 
     69   // Similar to StartProcess(), with the following differences:
     70   // - environment variables are not supported (no need yet)
     71   // - terminate_with_parent is not supported (may be non-trivial)
     72   // - the child process will run as |user| and |group|
     73   // - the |capmask| argument can be used to provide the child process
     74   //   with capabilities, which |user| might not have on its own
     75   virtual pid_t StartProcessInMinijail(
     76       const tracked_objects::Location& spawn_source,
     77       const base::FilePath& program,
     78       const std::vector<std::string>& arguments,
     79       const std::string& user,
     80       const std::string& group,
     81       uint64_t capmask,
     82       const base::Callback<void(int)>& exit_callback) {
     83     return StartProcessInMinijailWithPipes(
     84         spawn_source, program, arguments, user, group, capmask, exit_callback,
     85         nullptr, nullptr, nullptr);
     86   }
     87 
     88   // Similar to StartProcessInMinijail(), with the additional ability to
     89   // pipe the child's stdin/stdout/stderr back to us. If any of those
     90   // streams is not needed, simply pass nullptr for the corresponding
     91   // 'fd' argument. If no pipes are needed, use StartProcessInMinijail().
     92   virtual pid_t StartProcessInMinijailWithPipes(
     93       const tracked_objects::Location& spawn_source,
     94       const base::FilePath& program,
     95       const std::vector<std::string>& arguments,
     96       const std::string& user,
     97       const std::string& group,
     98       uint64_t capmask,
     99       const base::Callback<void(int)>& exit_callback,
    100       int* stdin_fd,
    101       int* stdout_fd,
    102       int* stderr_fd);
    103 
    104   // Stop the given |pid|.  Previously registered |exit_callback| will be
    105   // unregistered, since the caller is not interested in this process anymore
    106   // and that callback might not be valid by the time this process terminates.
    107   // This will attempt to terminate the child process by sending a SIGTERM
    108   // signal first.  If the process doesn't terminate within a certain time,
    109   // ProcessManager will attempt to send a SIGKILL signal.  It will give up
    110   // with an error log If the process still doesn't terminate within a certain
    111   // time.
    112   virtual bool StopProcess(pid_t pid);
    113 
    114   // Stop the given |pid| in a synchronous manner.
    115   virtual bool StopProcessAndBlock(pid_t pid);
    116 
    117   // Replace the current exit callback for |pid| with |new_callback|.
    118   virtual bool UpdateExitCallback(
    119       pid_t pid,
    120       const base::Callback<void(int)>& new_callback);
    121 
    122  protected:
    123   ProcessManager();
    124 
    125  private:
    126   friend class ProcessManagerTest;
    127   friend struct base::DefaultLazyInstanceTraits<ProcessManager>;
    128 
    129   using TerminationTimeoutCallback = base::CancelableClosure;
    130 
    131   // Invoked when process |pid| exited.
    132   void OnProcessExited(pid_t pid, const siginfo_t& info);
    133 
    134   // Invoked when process |pid| did not terminate within a certain timeout.
    135   // |kill_signal| indicates the signal used for termination. When it is set
    136   // to true, SIGKILL was used to terminate the process, otherwise, SIGTERM
    137   // was used.
    138   void ProcessTerminationTimeoutHandler(pid_t pid, bool kill_signal);
    139 
    140   // Send a termination signal to process |pid|. If |kill_signal| is set to
    141   // true, SIGKILL is sent, otherwise, SIGTERM is sent.  After signal is sent,
    142   // |pid| and timeout handler is added to |pending_termination_processes_|
    143   // list, to make sure process |pid| does exit in timely manner.
    144   bool TerminateProcess(pid_t pid, bool kill_signal);
    145 
    146   // Kill process |pid|. If |kill_signal| is true it will send SIGKILL,
    147   // otherwise it will send SIGTERM.
    148   // It returns true when the process was already dead or killed within
    149   // the timeout.
    150   // It returns false when the process failed to exit within the timeout
    151   // or the system failed to send kill singal.
    152   bool KillProcessWithTimeout(pid_t pid, bool kill_signal);
    153 
    154   // Kill process |pid| using signal |signal|.
    155   // The |killed| will be set true when the process was already dead.
    156   // It returns true when it sent the |signal| successfully or the
    157   // process was already dead.
    158   // It returns false when the system failed to send |signal|.
    159   bool KillProcess(pid_t pid, int signal, bool* killed);
    160 
    161   // Wait for process |pid| to exit. This function will check it for at most
    162   // |tries| times. The interval of waiting time grows exponentially from
    163   // |sleep_ms| and it has an |upper_bound_ms| upper bound.
    164   bool WaitpidWithTimeout(pid_t pid,
    165                           unsigned int sleep_ms,
    166                           unsigned int upper_bound_ms,
    167                           int tries);
    168 
    169   // Used to watch processes.
    170   std::unique_ptr<brillo::AsynchronousSignalHandler> async_signal_handler_;
    171   brillo::ProcessReaper process_reaper_;
    172 
    173   EventDispatcher* dispatcher_;
    174   brillo::Minijail* minijail_;
    175 
    176   // Processes to watch for the caller.
    177   std::map<pid_t, base::Callback<void(int)>> watched_processes_;
    178   // Processes being terminated by us.  Use a timer to make sure process
    179   // does exit, log an error if it failed to exit within a specific timeout.
    180   std::map<pid_t, std::unique_ptr<TerminationTimeoutCallback>>
    181       pending_termination_processes_;
    182 
    183   base::WeakPtrFactory<ProcessManager> weak_factory_{this};
    184   DISALLOW_COPY_AND_ASSIGN(ProcessManager);
    185 };
    186 
    187 }  // namespace shill
    188 
    189 #endif  // SHILL_PROCESS_MANAGER_H_
    190