1 // Copyright 2010 Google Inc. 2 // All rights reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // * Neither the name of Google Inc. nor the names of its contributors 14 // may be used to endorse or promote products derived from this software 15 // without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #include "utils/process/child.ipp" 30 31 extern "C" { 32 #include <sys/stat.h> 33 #include <sys/wait.h> 34 35 #include <fcntl.h> 36 #include <signal.h> 37 #include <unistd.h> 38 } 39 40 #include <cassert> 41 #include <cerrno> 42 #include <cstdlib> 43 #include <cstring> 44 #include <iostream> 45 #include <memory> 46 47 #include "utils/defs.hpp" 48 #include "utils/format/macros.hpp" 49 #include "utils/logging/macros.hpp" 50 #include "utils/process/exceptions.hpp" 51 #include "utils/process/fdstream.hpp" 52 #include "utils/process/system.hpp" 53 #include "utils/process/status.hpp" 54 #include "utils/sanity.hpp" 55 #include "utils/signals/interrupts.hpp" 56 57 58 namespace utils { 59 namespace process { 60 61 62 /// Private implementation fields for child objects. 63 struct child::impl { 64 /// The process identifier. 65 pid_t _pid; 66 67 /// The input stream for the process' stdout and stderr. May be NULL. 68 std::unique_ptr< process::ifdstream > _output; 69 70 /// Initializes private implementation data. 71 /// 72 /// \param pid The process identifier. 73 /// \param output The input stream. Grabs ownership of the pointer. 74 impl(const pid_t pid, process::ifdstream* output) : 75 _pid(pid), _output(output) {} 76 }; 77 78 79 } // namespace process 80 } // namespace utils 81 82 83 namespace fs = utils::fs; 84 namespace process = utils::process; 85 namespace signals = utils::signals; 86 87 88 namespace { 89 90 91 /// Exception-based version of dup(2). 92 /// 93 /// \param old_fd The file descriptor to duplicate. 94 /// \param new_fd The file descriptor to use as the duplicate. This is 95 /// closed if it was open before the copy happens. 96 /// 97 /// \throw process::system_error If the call to dup2(2) fails. 98 static void 99 safe_dup(const int old_fd, const int new_fd) 100 { 101 if (process::detail::syscall_dup2(old_fd, new_fd) == -1) { 102 const int original_errno = errno; 103 throw process::system_error(F("dup2(%s, %s) failed") % old_fd % new_fd, 104 original_errno); 105 } 106 } 107 108 109 /// Exception-based version of open(2) to open (or create) a file for append. 110 /// 111 /// \param filename The file to open in append mode. 112 /// 113 /// \return The file descriptor for the opened or created file. 114 /// 115 /// \throw process::system_error If the call to open(2) fails. 116 static int 117 open_for_append(const fs::path& filename) 118 { 119 const int fd = process::detail::syscall_open( 120 filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 121 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 122 if (fd == -1) { 123 const int original_errno = errno; 124 throw process::system_error(F("Failed to create %s because open(2) " 125 "failed") % filename, original_errno); 126 } 127 return fd; 128 } 129 130 131 /// Exception-based, type-improved version of wait(2). 132 /// 133 /// Because we are waiting for the termination of a process, and because this is 134 /// the canonical way to call wait(2) for this module, we ensure from here that 135 /// any subprocess of the process we are killing is terminated. 136 /// 137 /// \param pid The identifier of the process to wait for. 138 /// 139 /// \return The termination status of the process. 140 /// 141 /// \throw process::system_error If the call to waitpid(2) fails. 142 static process::status 143 safe_wait(const pid_t pid) 144 { 145 LD(F("Waiting for pid=%s") % pid); 146 int stat_loc; 147 if (process::detail::syscall_waitpid(pid, &stat_loc, 0) == -1) { 148 const int original_errno = errno; 149 throw process::system_error(F("Failed to wait for PID %s") % pid, 150 original_errno); 151 } 152 return process::status(pid, stat_loc); 153 } 154 155 156 /// Logs the execution of another program. 157 /// 158 /// \param program The binary to execute. 159 /// \param args The arguments to pass to the binary, without the program name. 160 static void 161 log_exec(const fs::path& program, const process::args_vector& args) 162 { 163 std::string plain_command = program.str(); 164 for (process::args_vector::const_iterator iter = args.begin(); 165 iter != args.end(); ++iter) 166 plain_command += F(" %s") % *iter; 167 LD(F("Executing %s") % plain_command); 168 } 169 170 171 /// Maximum number of arguments supported by cxx_exec. 172 /// 173 /// We need this limit to avoid having to allocate dynamic memory in the child 174 /// process to construct the arguments list, which would have side-effects in 175 /// the parent's memory if we use vfork(). 176 #define MAX_ARGS 128 177 178 179 static void cxx_exec(const fs::path& program, const process::args_vector& args) 180 throw() UTILS_NORETURN; 181 182 183 /// Executes an external binary and replaces the current process. 184 /// 185 /// This function must not use any of the logging features, so that the output 186 /// of the subprocess is not "polluted" by our own messages. 187 /// 188 /// This function must also not affect the global state of the current process 189 /// as otherwise we would not be able to use vfork(). Only state stored in the 190 /// stack can be touched. 191 /// 192 /// \param program The binary to execute. 193 /// \param args The arguments to pass to the binary, without the program name. 194 static void 195 cxx_exec(const fs::path& program, const process::args_vector& args) throw() 196 { 197 assert(args.size() < MAX_ARGS); 198 try { 199 const char* argv[MAX_ARGS + 1]; 200 201 argv[0] = program.c_str(); 202 for (process::args_vector::size_type i = 0; i < args.size(); i++) 203 argv[1 + i] = args[i].c_str(); 204 argv[1 + args.size()] = NULL; 205 206 const int ret = ::execv(program.c_str(), 207 (char* const*)(unsigned long)(const void*)argv); 208 const int original_errno = errno; 209 assert(ret == -1); 210 211 std::cerr << "Failed to execute " << program << ": " 212 << std::strerror(original_errno) << "\n"; 213 std::abort(); 214 } catch (const std::runtime_error& error) { 215 std::cerr << "Failed to execute " << program << ": " 216 << error.what() << "\n"; 217 std::abort(); 218 } catch (...) { 219 std::cerr << "Failed to execute " << program << "; got unexpected " 220 "exception during exec\n"; 221 std::abort(); 222 } 223 } 224 225 226 } // anonymous namespace 227 228 229 /// Creates a new child. 230 /// 231 /// \param implptr A dynamically-allocated impl object with the contents of the 232 /// new child. 233 process::child::child(impl *implptr) : 234 _pimpl(implptr) 235 { 236 } 237 238 239 /// Destructor for child. 240 process::child::~child(void) 241 { 242 } 243 244 245 /// Helper function for fork(). 246 /// 247 /// Please note: if you update this function to change the return type or to 248 /// raise different errors, do not forget to update fork() accordingly. 249 /// 250 /// \return In the case of the parent, a new child object returned as a 251 /// dynamically-allocated object because children classes are unique and thus 252 /// noncopyable. In the case of the child, a NULL pointer. 253 /// 254 /// \throw process::system_error If the calls to pipe(2) or fork(2) fail. 255 std::unique_ptr< process::child > 256 process::child::fork_capture_aux(void) 257 { 258 std::cout.flush(); 259 std::cerr.flush(); 260 261 int fds[2]; 262 if (detail::syscall_pipe(fds) == -1) 263 throw process::system_error("pipe(2) failed", errno); 264 265 std::unique_ptr< signals::interrupts_inhibiter > inhibiter( 266 new signals::interrupts_inhibiter); 267 pid_t pid = detail::syscall_fork(); 268 if (pid == -1) { 269 inhibiter.reset(NULL); // Unblock signals. 270 ::close(fds[0]); 271 ::close(fds[1]); 272 throw process::system_error("fork(2) failed", errno); 273 } else if (pid == 0) { 274 inhibiter.reset(NULL); // Unblock signals. 275 ::setpgid(::getpid(), ::getpid()); 276 277 try { 278 ::close(fds[0]); 279 safe_dup(fds[1], STDOUT_FILENO); 280 safe_dup(fds[1], STDERR_FILENO); 281 ::close(fds[1]); 282 } catch (const system_error& e) { 283 std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); 284 std::abort(); 285 } 286 return std::unique_ptr< process::child >(); 287 } else { 288 ::close(fds[1]); 289 LD(F("Spawned process %s: stdout and stderr inherited") % pid); 290 signals::add_pid_to_kill(pid); 291 inhibiter.reset(NULL); // Unblock signals. 292 return std::unique_ptr< process::child >( 293 new process::child(new impl(pid, new process::ifdstream(fds[0])))); 294 } 295 } 296 297 298 /// Helper function for fork(). 299 /// 300 /// Please note: if you update this function to change the return type or to 301 /// raise different errors, do not forget to update fork() accordingly. 302 /// 303 /// \param stdout_file The name of the file in which to store the stdout. 304 /// If this has the magic value /dev/stdout, then the parent's stdout is 305 /// reused without applying any redirection. 306 /// \param stderr_file The name of the file in which to store the stderr. 307 /// If this has the magic value /dev/stderr, then the parent's stderr is 308 /// reused without applying any redirection. 309 /// 310 /// \return In the case of the parent, a new child object returned as a 311 /// dynamically-allocated object because children classes are unique and thus 312 /// noncopyable. In the case of the child, a NULL pointer. 313 /// 314 /// \throw process::system_error If the call to fork(2) fails. 315 std::unique_ptr< process::child > 316 process::child::fork_files_aux(const fs::path& stdout_file, 317 const fs::path& stderr_file) 318 { 319 std::cout.flush(); 320 std::cerr.flush(); 321 322 std::unique_ptr< signals::interrupts_inhibiter > inhibiter( 323 new signals::interrupts_inhibiter); 324 pid_t pid = detail::syscall_fork(); 325 if (pid == -1) { 326 inhibiter.reset(NULL); // Unblock signals. 327 throw process::system_error("fork(2) failed", errno); 328 } else if (pid == 0) { 329 inhibiter.reset(NULL); // Unblock signals. 330 ::setpgid(::getpid(), ::getpid()); 331 332 try { 333 if (stdout_file != fs::path("/dev/stdout")) { 334 const int stdout_fd = open_for_append(stdout_file); 335 safe_dup(stdout_fd, STDOUT_FILENO); 336 ::close(stdout_fd); 337 } 338 if (stderr_file != fs::path("/dev/stderr")) { 339 const int stderr_fd = open_for_append(stderr_file); 340 safe_dup(stderr_fd, STDERR_FILENO); 341 ::close(stderr_fd); 342 } 343 } catch (const system_error& e) { 344 std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); 345 std::abort(); 346 } 347 return std::unique_ptr< process::child >(); 348 } else { 349 LD(F("Spawned process %s: stdout=%s, stderr=%s") % pid % stdout_file % 350 stderr_file); 351 signals::add_pid_to_kill(pid); 352 inhibiter.reset(NULL); // Unblock signals. 353 return std::unique_ptr< process::child >( 354 new process::child(new impl(pid, NULL))); 355 } 356 } 357 358 359 /// Spawns a new binary and multiplexes and captures its stdout and stderr. 360 /// 361 /// If the subprocess cannot be completely set up for any reason, it attempts to 362 /// dump an error message to its stderr channel and it then calls std::abort(). 363 /// 364 /// \param program The binary to execute. 365 /// \param args The arguments to pass to the binary, without the program name. 366 /// 367 /// \return A new child object, returned as a dynamically-allocated object 368 /// because children classes are unique and thus noncopyable. 369 /// 370 /// \throw process::system_error If the process cannot be spawned due to a 371 /// system call error. 372 std::unique_ptr< process::child > 373 process::child::spawn_capture(const fs::path& program, const args_vector& args) 374 { 375 std::unique_ptr< child > child = fork_capture_aux(); 376 if (child.get() == NULL) 377 cxx_exec(program, args); 378 log_exec(program, args); 379 return child; 380 } 381 382 383 /// Spawns a new binary and redirects its stdout and stderr to files. 384 /// 385 /// If the subprocess cannot be completely set up for any reason, it attempts to 386 /// dump an error message to its stderr channel and it then calls std::abort(). 387 /// 388 /// \param program The binary to execute. 389 /// \param args The arguments to pass to the binary, without the program name. 390 /// \param stdout_file The name of the file in which to store the stdout. 391 /// \param stderr_file The name of the file in which to store the stderr. 392 /// 393 /// \return A new child object, returned as a dynamically-allocated object 394 /// because children classes are unique and thus noncopyable. 395 /// 396 /// \throw process::system_error If the process cannot be spawned due to a 397 /// system call error. 398 std::unique_ptr< process::child > 399 process::child::spawn_files(const fs::path& program, 400 const args_vector& args, 401 const fs::path& stdout_file, 402 const fs::path& stderr_file) 403 { 404 std::unique_ptr< child > child = fork_files_aux(stdout_file, stderr_file); 405 if (child.get() == NULL) 406 cxx_exec(program, args); 407 log_exec(program, args); 408 return child; 409 } 410 411 412 /// Returns the process identifier of this child. 413 /// 414 /// \return A process identifier. 415 int 416 process::child::pid(void) const 417 { 418 return _pimpl->_pid; 419 } 420 421 422 /// Gets the input stream corresponding to the stdout and stderr of the child. 423 /// 424 /// \pre The child must have been started by fork_capture(). 425 /// 426 /// \return A reference to the input stream connected to the output of the test 427 /// case. 428 std::istream& 429 process::child::output(void) 430 { 431 PRE(_pimpl->_output.get() != NULL); 432 return *_pimpl->_output; 433 } 434 435 436 /// Blocks to wait for completion. 437 /// 438 /// \return The termination status of the child process. 439 /// 440 /// \throw process::system_error If the call to waitpid(2) fails. 441 process::status 442 process::child::wait(void) 443 { 444 const process::status status = safe_wait(_pimpl->_pid); 445 { 446 signals::interrupts_inhibiter inhibiter; 447 signals::remove_pid_to_kill(_pimpl->_pid); 448 } 449 return status; 450 } 451