Apache Mesos
subprocess.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License
12 
13 #ifndef __PROCESS_WINDOWS_SUBPROCESS_HPP__
14 #define __PROCESS_WINDOWS_SUBPROCESS_HPP__
15 
16 #include <signal.h>
17 
18 #include <array>
19 #include <string>
20 
21 #include <glog/logging.h>
22 
23 #include <process/subprocess.hpp>
24 
25 #include <stout/error.hpp>
26 #include <stout/foreach.hpp>
27 #include <stout/hashset.hpp>
28 #include <stout/option.hpp>
29 #include <stout/try.hpp>
30 #include <stout/windows.hpp>
31 
32 #include <stout/os/close.hpp>
33 #include <stout/os/environment.hpp>
34 #include <stout/os/exec.hpp>
35 
36 #include <userEnv.h>
37 
38 namespace process {
39 namespace internal {
40 
41 // NOTE: We are expecting that components of `argv` that need to be quoted
42 // (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
43 // to have been already quoted correctly before we generate `command`.
44 // Incorrectly-quoted command arguments will probably lead the child process
45 // to terminate with an error. See also NOTE on `process::subprocess`.
47  const std::string& path,
48  const std::vector<std::string>& argv,
49  const Option<std::map<std::string, std::string>>& environment,
50  const std::vector<Subprocess::ParentHook>& parent_hooks,
51  const InputFileDescriptors& stdinfds,
52  const OutputFileDescriptors& stdoutfds,
53  const OutputFileDescriptors& stderrfds,
54  const std::vector<int_fd>& whitelist_fds = {})
55 {
56  const std::array<int_fd, 3> fds{
57  stdinfds.read, stdoutfds.write, stderrfds.write};
58 
61  path,
62  argv,
64  true, // Create suspended.
65  fds,
66  whitelist_fds);
67 
68  // Close the child-ends of the file descriptors that are created
69  // by this function.
70  foreach (const int_fd& fd, fds) {
71  if (fd.is_valid()) {
72  Try<Nothing> result = os::close(fd);
73  if (result.isError()) {
74  return Error(result.error());
75  }
76  }
77  }
78 
79  if (process_data.isError()) {
80  return Error(process_data.error());
81  }
82 
83  // Run the parent hooks.
84  const pid_t pid = process_data->pid;
85  foreach (const Subprocess::ParentHook& hook, parent_hooks) {
86  Try<Nothing> parent_setup = hook.parent_setup(pid);
87 
88  // If the hook callback fails, we shouldn't proceed with the
89  // execution and hence the child process should be killed.
90  if (parent_setup.isError()) {
91  // Attempt to kill the process. Since it is still in suspended state, we
92  // do not need to kill any descendents. We also can't use `os::kill_job`
93  // because this process is not in a Job Object unless one of the parent
94  // hooks added it.
95  ::TerminateProcess(process_data->process_handle.get_handle(), 1);
96 
97  return Error(
98  "Failed to execute Parent Hook in child '" + stringify(pid) +
99  "' with command '" + stringify(argv) + "': " +
100  parent_setup.error());
101  }
102  }
103 
104  // Start child process.
105  if (::ResumeThread(process_data->thread_handle.get_handle()) == -1) {
106  return WindowsError(
107  "Failed to resume child process with command '" +
108  stringify(argv) + "'");
109  }
110 
111  return process_data;
112 }
113 
114 } // namespace internal {
115 } // namespace process {
116 
117 #endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__
Definition: path.hpp:29
Definition: errorbase.hpp:36
Definition: option.hpp:29
Try< os::windows::internal::ProcessData > createChildProcess(const std::string &path, const std::vector< std::string > &argv, const Option< std::map< std::string, std::string >> &environment, const std::vector< Subprocess::ParentHook > &parent_hooks, const InputFileDescriptors &stdinfds, const OutputFileDescriptors &stdoutfds, const OutputFileDescriptors &stderrfds, const std::vector< int_fd > &whitelist_fds={})
Definition: subprocess.hpp:46
HANDLE get_handle() const
Definition: windows.hpp:90
Definition: check.hpp:33
Try< ProcessData > create_process(const std::string &command, const std::vector< std::string > &argv, const Option< std::map< std::string, std::string >> &environment, const bool create_suspended=false, const Option< std::array< int_fd, 3 >> &pipes=None(), const std::vector< int_fd > &whitelist_fds={})
Definition: exec.hpp:263
Definition: error.hpp:108
int_fd read
Definition: subprocess.hpp:76
For output file descriptors a child writes to the write file descriptor and a parent may read from th...
Definition: subprocess.hpp:89
SharedHandle process_handle
Definition: exec.hpp:223
SharedHandle thread_handle
Definition: exec.hpp:224
Environment * environment
DWORD pid_t
Definition: windows.hpp:181
int_fd write
Definition: subprocess.hpp:92
Try< Nothing > close(int fd)
Definition: close.hpp:24
For input file descriptors a child reads from the read file descriptor and a parent may write to the ...
Definition: subprocess.hpp:74
static Try error(const E &e)
Definition: try.hpp:43
const lambda::function< Try< Nothing >pid_t)> parent_setup
The callback that must be specified for execution after the child has been cloned, but before it starts executing the new process.
Definition: subprocess.hpp:164
Definition: attributes.hpp:24
bool isError() const
Definition: try.hpp:78
Definition: executor.hpp:48
pid_t pid
Definition: exec.hpp:225
A hook can be passed to a subprocess call.
Definition: subprocess.hpp:153
int int_fd
Definition: int_fd.hpp:35
std::string stringify(int flags)