Apache Mesos
subprocess_windows.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/os.hpp>
30 #include <stout/os/shell.hpp>
31 #include <stout/try.hpp>
32 #include <stout/windows.hpp>
33 
34 #include <stout/os/close.hpp>
35 #include <stout/os/environment.hpp>
36 
37 #include <userEnv.h>
38 
39 namespace process {
40 namespace internal {
41 
42 // NOTE: We are expecting that components of `argv` that need to be quoted
43 // (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`)
44 // to have been already quoted correctly before we generate `command`.
45 // Incorrectly-quoted command arguments will probably lead the child process
46 // to terminate with an error. See also NOTE on `process::subprocess`.
48  const std::string& path,
49  const std::vector<std::string>& argv,
50  const Option<std::map<std::string, std::string>>& environment,
51  const std::vector<Subprocess::ParentHook>& parent_hooks,
52  const InputFileDescriptors& stdinfds,
53  const OutputFileDescriptors& stdoutfds,
54  const OutputFileDescriptors& stderrfds,
55  const std::vector<int_fd>& whitelist_fds = {})
56 {
57  const std::array<int_fd, 3> fds{
58  stdinfds.read, stdoutfds.write, stderrfds.write};
59 
62  path,
63  argv,
65  true, // Create suspended.
66  fds,
67  whitelist_fds);
68 
69  // Close the child-ends of the file descriptors that are created
70  // by this function.
71  foreach (const int_fd& fd, fds) {
72  if (fd.is_valid()) {
73  Try<Nothing> result = os::close(fd);
74  if (result.isError()) {
75  return Error(result.error());
76  }
77  }
78  }
79 
80  if (process_data.isError()) {
81  return Error(process_data.error());
82  }
83 
84  // Run the parent hooks.
85  const pid_t pid = process_data->pid;
86  foreach (const Subprocess::ParentHook& hook, parent_hooks) {
87  Try<Nothing> parent_setup = hook.parent_setup(pid);
88 
89  // If the hook callback fails, we shouldn't proceed with the
90  // execution and hence the child process should be killed.
91  if (parent_setup.isError()) {
92  // Attempt to kill the process. Since it is still in suspended state, we
93  // do not need to kill any descendents. We also can't use `os::kill_job`
94  // because this process is not in a Job Object unless one of the parent
95  // hooks added it.
96  ::TerminateProcess(process_data->process_handle.get_handle(), 1);
97 
98  return Error(
99  "Failed to execute Parent Hook in child '" + stringify(pid) +
100  "' with command '" + stringify(argv) + "': " +
101  parent_setup.error());
102  }
103  }
104 
105  // Start child process.
106  if (::ResumeThread(process_data->thread_handle.get_handle()) == -1) {
107  return WindowsError(
108  "Failed to resume child process with command '" +
109  stringify(argv) + "'");
110  }
111 
112  return process_data;
113 }
114 
115 } // namespace internal {
116 } // namespace process {
117 
118 #endif // __PROCESS_WINDOWS_SUBPROCESS_HPP__
Definition: path.hpp:26
Definition: errorbase.hpp:36
Definition: option.hpp:28
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: shell.hpp:240
HANDLE get_handle() const
Definition: windows.hpp:90
Definition: check.hpp:33
Definition: error.hpp:108
int_fd read
Definition: subprocess.hpp:75
For output file descriptors a child writes to the write file descriptor and a parent may read from th...
Definition: subprocess.hpp:88
Try<::internal::windows::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_windows.hpp:47
Environment * environment
DWORD pid_t
Definition: windows.hpp:181
int_fd write
Definition: subprocess.hpp:91
Try< Nothing > close(int fd)
Definition: close.hpp:24
SharedHandle process_handle
Definition: shell.hpp:214
SharedHandle thread_handle
Definition: shell.hpp:215
For input file descriptors a child reads from the read file descriptor and a parent may write to the ...
Definition: subprocess.hpp:73
static Try error(const E &e)
Definition: try.hpp:42
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:163
Definition: attributes.hpp:24
bool isError() const
Definition: try.hpp:71
Definition: executor.hpp:48
pid_t pid
Definition: shell.hpp:216
A hook can be passed to a subprocess call.
Definition: subprocess.hpp:152
int int_fd
Definition: int_fd.hpp:35
std::string stringify(int flags)