NOTE: We are expecting that components of `argv` that need to be quoted (for example, paths with spaces in them like `C:\"Program Files"\foo.exe`) to have been already quoted correctly before we generate `command`. Incorrectly-quoted command arguments will probably lead the child process to terminate with an error. See also NOTE on `process::subprocess`.
| 44 | // Incorrectly-quoted command arguments will probably lead the child process |
| 45 | // to terminate with an error. See also NOTE on `process::subprocess`. |
| 46 | inline Try<os::windows::internal::ProcessData> createChildProcess( |
| 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 | |
| 59 | Try<os::windows::internal::ProcessData> process_data = |
| 60 | os::windows::internal::create_process( |
| 61 | path, |
| 62 | argv, |
| 63 | environment, |
| 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 |
no test coverage detected