// Copyright 2018 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 SHILL_PROCESS_MANAGER_H_
#define SHILL_PROCESS_MANAGER_H_

#include <map>
#include <memory>
#include <string>
#include <vector>

#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <base/files/file_path.h>
#include <base/lazy_instance.h>
#include <base/location.h>
#include <base/memory/weak_ptr.h>
#include <brillo/minijail/minijail.h>
#include <brillo/process.h>
#include <brillo/process_reaper.h>
#include <libminijail.h>

namespace shill {

struct std_file_descriptors {
  int* stdin_fd;
  int* stdout_fd;
  int* stderr_fd;
};

class EventDispatcher;

// The ProcessManager is a singleton providing process creation and
// asynchronous process termination. Need to initialize it once with
// Init method call.
class ProcessManager {
 public:
  virtual ~ProcessManager();

  // This is a singleton -- use ProcessManager::GetInstance()->Foo().
  static ProcessManager* GetInstance();

  // Register async signal handler and setup process reaper.
  virtual void Init(EventDispatcher* dispatcher);

  // Call on shutdown to release async_signal_handler_.
  virtual void Stop();

  // Create and start a process for |program| with |arguments|. |environment|
  // variables will be setup in the child process before exec the |program|.
  // |terminate_with_parent| is used to indicate if child process should
  // self terminate if the parent process exits.  |exit_callback| will be
  // invoked when child process exits (not terminated by us).  Return -1
  // if failed to start the process, otherwise, return the pid of the child
  // process.
  virtual pid_t StartProcess(
      const base::Location& spawn_source,
      const base::FilePath& program,
      const std::vector<std::string>& arguments,
      const std::map<std::string, std::string>& environment,
      bool terminate_with_parent,
      const base::Callback<void(int)>& exit_callback);

  // Similar to StartProcess(), with the following differences:
  // - terminate_with_parent is not supported (may be non-trivial)
  // - the child process will run as |user| and |group|
  // - the |capmask| argument can be used to provide the child process
  //   with capabilities, which |user| might not have on its own
  // - the |inherit_supplementary_groups| argument allows child process to
  //   inherit supplementary groups from uid, equivalent to using '-G' on the
  //   minijail command line.
  virtual pid_t StartProcessInMinijail(
      const base::Location& spawn_source,
      const base::FilePath& program,
      const std::vector<std::string>& arguments,
      const std::map<std::string, std::string>& environment,
      const std::string& user,
      const std::string& group,
      uint64_t capmask,
      bool inherit_supplementary_groups,
      bool close_nonstd_fds,
      const base::Callback<void(int)>& exit_callback) {
    return StartProcessInMinijailWithPipes(
        spawn_source, program, arguments, environment, user, group, capmask,
        inherit_supplementary_groups, close_nonstd_fds, exit_callback,
        (struct std_file_descriptors){nullptr, nullptr, nullptr});
  }

  // Similar to StartProcessInMinijail(), with the additional ability to
  // pipe the child's stdin/stdout/stderr back to us. If any of those
  // streams is not needed, simply pass nullptr for the corresponding
  // member in std file descriptor struct. If no pipes are needed, use
  // StartProcessInMinijail().
  virtual pid_t StartProcessInMinijailWithPipes(
      const base::Location& spawn_source,
      const base::FilePath& program,
      const std::vector<std::string>& arguments,
      const std::map<std::string, std::string>& environment,
      const std::string& user,
      const std::string& group,
      uint64_t capmask,
      bool inherit_supplementary_groups,
      bool close_nonstd_fds,
      const base::Callback<void(int)>& exit_callback,
      struct std_file_descriptors std_fds);

  // Stop the given |pid|.  Previously registered |exit_callback| will be
  // unregistered, since the caller is not interested in this process anymore
  // and that callback might not be valid by the time this process terminates.
  // This will attempt to terminate the child process by sending a SIGTERM
  // signal first.  If the process doesn't terminate within a certain time,
  // ProcessManager will attempt to send a SIGKILL signal.  It will give up
  // with an error log If the process still doesn't terminate within a certain
  // time.
  virtual bool StopProcess(pid_t pid);

  // Stop the given |pid| in a synchronous manner.
  virtual bool StopProcessAndBlock(pid_t pid);

  // Replace the current exit callback for |pid| with |new_callback|.
  virtual bool UpdateExitCallback(
      pid_t pid, const base::Callback<void(int)>& new_callback);

 protected:
  ProcessManager();

 private:
  friend class ProcessManagerTest;
  friend base::LazyInstanceTraitsBase<ProcessManager>;

  using TerminationTimeoutCallback = base::CancelableClosure;

  // Invoked when process |pid| exited.
  void OnProcessExited(pid_t pid, const siginfo_t& info);

  // Invoked when process |pid| did not terminate within a certain timeout.
  // |kill_signal| indicates the signal used for termination. When it is set
  // to true, SIGKILL was used to terminate the process, otherwise, SIGTERM
  // was used.
  void ProcessTerminationTimeoutHandler(pid_t pid, bool kill_signal);

  // Send a termination signal to process |pid|. If |kill_signal| is set to
  // true, SIGKILL is sent, otherwise, SIGTERM is sent.  After signal is sent,
  // |pid| and timeout handler is added to |pending_termination_processes_|
  // list, to make sure process |pid| does exit in timely manner.
  bool TerminateProcess(pid_t pid, bool kill_signal);

  // Kill process |pid|. If |kill_signal| is true it will send SIGKILL,
  // otherwise it will send SIGTERM.
  // It returns true when the process was already dead or killed within
  // the timeout.
  // It returns false when the process failed to exit within the timeout
  // or the system failed to send kill singal.
  bool KillProcessWithTimeout(pid_t pid, bool kill_signal);

  // Kill process |pid| using signal |signal|.
  // The |killed| will be set true when the process was already dead.
  // It returns true when it sent the |signal| successfully or the
  // process was already dead.
  // It returns false when the system failed to send |signal|.
  bool KillProcess(pid_t pid, int signal, bool* killed);

  // Wait for process |pid| to exit. This function will check it for at most
  // |tries| times. The interval of waiting time grows exponentially from
  // |sleep_ms| and it has an |upper_bound_ms| upper bound.
  bool WaitpidWithTimeout(pid_t pid,
                          unsigned int sleep_ms,
                          unsigned int upper_bound_ms,
                          int tries);

  // Used to watch processes.
  std::unique_ptr<brillo::AsynchronousSignalHandler> async_signal_handler_;
  brillo::ProcessReaper process_reaper_;

  EventDispatcher* dispatcher_;
  brillo::Minijail* minijail_;

  // Processes to watch for the caller.
  std::map<pid_t, base::Callback<void(int)>> watched_processes_;
  // Processes being terminated by us.  Use a timer to make sure process
  // does exit, log an error if it failed to exit within a specific timeout.
  std::map<pid_t, std::unique_ptr<TerminationTimeoutCallback>>
      pending_termination_processes_;

  base::WeakPtrFactory<ProcessManager> weak_factory_{this};
  DISALLOW_COPY_AND_ASSIGN(ProcessManager);
};

}  // namespace shill

#endif  // SHILL_PROCESS_MANAGER_H_
