PageRenderTime 202ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/3rdparty/libprocess/include/process/subprocess.hpp

https://gitlab.com/huayuting/mesos
C++ Header | 171 lines | 109 code | 30 blank | 32 comment | 3 complexity | bd066c93ddd0c56abdbe2fbaed6dc76e MD5 | raw file
  1. #ifndef __PROCESS_SUBPROCESS_HPP__
  2. #define __PROCESS_SUBPROCESS_HPP__
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <map>
  6. #include <string>
  7. #include <process/future.hpp>
  8. #include <stout/flags.hpp>
  9. #include <stout/lambda.hpp>
  10. #include <stout/memory.hpp>
  11. #include <stout/option.hpp>
  12. #include <stout/os.hpp>
  13. #include <stout/try.hpp>
  14. namespace process {
  15. // Represents a fork() exec()ed subprocess. Access is provided to
  16. // the input / output of the process, as well as the exit status.
  17. // The input / output file descriptors are only closed after both:
  18. // 1. The subprocess has terminated, and
  19. // 2. There are no longer any references to the associated
  20. // Subprocess object.
  21. class Subprocess
  22. {
  23. public:
  24. // Describes how the I/O is redirected for stdin/stdout/stderr.
  25. // One of the following three modes are supported:
  26. // 1. PIPE: Redirect to a pipe. The pipe will be created
  27. // automatically and the user can read/write the parent side of
  28. // the pipe from in()/out()/err().
  29. // 2. PATH: Redirect to a file. The file will be created if it
  30. // does not exist. If the file exists, it will be appended.
  31. // 3. FD: Redirect to an open file descriptor.
  32. class IO
  33. {
  34. private:
  35. friend class Subprocess;
  36. friend Try<Subprocess> subprocess(
  37. const std::string& command,
  38. const IO& in,
  39. const IO& out,
  40. const IO& err,
  41. const Option<flags::FlagsBase>& flags,
  42. const Option<std::map<std::string, std::string> >& environment,
  43. const Option<lambda::function<int()> >& setup);
  44. enum Mode
  45. {
  46. PIPE, // Redirect I/O to a pipe.
  47. PATH, // Redirect I/O to a file.
  48. FD, // Redirect I/O to an open file descriptor.
  49. };
  50. IO(Mode _mode, const Option<int>& _fd, const Option<std::string>& _path)
  51. : mode(_mode), fd(_fd), path(_path) {}
  52. Mode mode;
  53. Option<int> fd;
  54. Option<std::string> path;
  55. };
  56. // Syntactic sugar to create IO descriptors.
  57. static IO PIPE()
  58. {
  59. return IO(IO::PIPE, None(), None());
  60. }
  61. static IO PATH(const std::string& path)
  62. {
  63. return IO(IO::PATH, None(), path);
  64. }
  65. static IO FD(int fd)
  66. {
  67. return IO(IO::FD, fd, None());
  68. }
  69. // Returns the pid for the subprocess.
  70. pid_t pid() const { return data->pid; }
  71. // The parent side of the pipe for stdin/stdout/stderr.
  72. Option<int> in() const { return data->in; }
  73. Option<int> out() const { return data->out; }
  74. Option<int> err() const { return data->err; }
  75. // Returns a future from process::reap of this subprocess.
  76. // Discarding this future has no effect on the subprocess.
  77. Future<Option<int> > status() const { return data->status; }
  78. private:
  79. friend Try<Subprocess> subprocess(
  80. const std::string& command,
  81. const IO& in,
  82. const IO& out,
  83. const IO& err,
  84. const Option<flags::FlagsBase>& flags,
  85. const Option<std::map<std::string, std::string> >& environment,
  86. const Option<lambda::function<int()> >& setup);
  87. struct Data
  88. {
  89. ~Data()
  90. {
  91. if (in.isSome()) { os::close(in.get()); }
  92. if (out.isSome()) { os::close(out.get()); }
  93. if (err.isSome()) { os::close(err.get()); }
  94. }
  95. pid_t pid;
  96. // The parent side of the pipe for stdin/stdout/stderr. If the
  97. // mode is not PIPE, None will be stored.
  98. // NOTE: stdin, stdout, stderr are macros on some systems, hence
  99. // these names instead.
  100. Option<int> in;
  101. Option<int> out;
  102. Option<int> err;
  103. Future<Option<int> > status;
  104. };
  105. Subprocess() : data(new Data()) {}
  106. memory::shared_ptr<Data> data;
  107. };
  108. // The Environment is combined with the OS environment and overrides
  109. // where necessary.
  110. // The setup function is run after forking but before executing the
  111. // command. If the return value of that setup function is non-zero,
  112. // then that is what the subprocess status will be;
  113. // status = setup && command.
  114. // NOTE: Take extra care about the design of the setup function as it
  115. // must not contain any async unsafe code.
  116. // TODO(dhamon): Add an option to not combine the two environments.
  117. Try<Subprocess> subprocess(
  118. const std::string& command,
  119. const Subprocess::IO& in,
  120. const Subprocess::IO& out,
  121. const Subprocess::IO& err,
  122. const Option<flags::FlagsBase>& flags = None(),
  123. const Option<std::map<std::string, std::string> >& environment = None(),
  124. const Option<lambda::function<int()> >& setup = None());
  125. inline Try<Subprocess> subprocess(
  126. const std::string& command,
  127. const Option<flags::FlagsBase>& flags = None(),
  128. const Option<std::map<std::string, std::string> >& environment = None(),
  129. const Option<lambda::function<int()> >& setup = None())
  130. {
  131. return subprocess(
  132. command,
  133. Subprocess::FD(STDIN_FILENO),
  134. Subprocess::FD(STDOUT_FILENO),
  135. Subprocess::FD(STDERR_FILENO),
  136. flags,
  137. environment,
  138. setup);
  139. }
  140. } // namespace process {
  141. #endif // __PROCESS_SUBPROCESS_HPP__