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::auto_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 #if defined(__minix) && !defined(NDEBUG) 207 const int ret = 208 #endif /* defined(__minix) && !defined(NDEBUG) */ 209 ::execv(program.c_str(), 210 (char* const*)(unsigned long)(const void*)argv); 211 const int original_errno = errno; 212 assert(ret == -1); 213 214 std::cerr << "Failed to execute " << program << ": " 215 << std::strerror(original_errno) << "\n"; 216 std::abort(); 217 } catch (const std::runtime_error& error) { 218 std::cerr << "Failed to execute " << program << ": " 219 << error.what() << "\n"; 220 std::abort(); 221 } catch (...) { 222 std::cerr << "Failed to execute " << program << "; got unexpected " 223 "exception during exec\n"; 224 std::abort(); 225 } 226 } 227 228 229 } // anonymous namespace 230 231 232 /// Creates a new child. 233 /// 234 /// \param implptr A dynamically-allocated impl object with the contents of the 235 /// new child. 236 process::child::child(impl *implptr) : 237 _pimpl(implptr) 238 { 239 } 240 241 242 /// Destructor for child. 243 process::child::~child(void) 244 { 245 } 246 247 248 /// Helper function for fork(). 249 /// 250 /// Please note: if you update this function to change the return type or to 251 /// raise different errors, do not forget to update fork() accordingly. 252 /// 253 /// \return In the case of the parent, a new child object returned as a 254 /// dynamically-allocated object because children classes are unique and thus 255 /// noncopyable. In the case of the child, a NULL pointer. 256 /// 257 /// \throw process::system_error If the calls to pipe(2) or fork(2) fail. 258 std::auto_ptr< process::child > 259 process::child::fork_capture_aux(void) 260 { 261 std::cout.flush(); 262 std::cerr.flush(); 263 264 int fds[2]; 265 if (detail::syscall_pipe(fds) == -1) 266 throw process::system_error("pipe(2) failed", errno); 267 268 std::auto_ptr< signals::interrupts_inhibiter > inhibiter( 269 new signals::interrupts_inhibiter); 270 pid_t pid = detail::syscall_fork(); 271 if (pid == -1) { 272 inhibiter.reset(NULL); // Unblock signals. 273 ::close(fds[0]); 274 ::close(fds[1]); 275 throw process::system_error("fork(2) failed", errno); 276 } else if (pid == 0) { 277 inhibiter.reset(NULL); // Unblock signals. 278 #if !defined(__minix) 279 ::setpgid(::getpid(), ::getpid()); 280 #endif /* !defined(__minix) */ 281 282 try { 283 ::close(fds[0]); 284 safe_dup(fds[1], STDOUT_FILENO); 285 safe_dup(fds[1], STDERR_FILENO); 286 ::close(fds[1]); 287 } catch (const system_error& e) { 288 std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); 289 std::abort(); 290 } 291 return std::auto_ptr< process::child >(NULL); 292 } else { 293 ::close(fds[1]); 294 LD(F("Spawned process %s: stdout and stderr inherited") % pid); 295 signals::add_pid_to_kill(pid); 296 inhibiter.reset(NULL); // Unblock signals. 297 return std::auto_ptr< process::child >( 298 new process::child(new impl(pid, new process::ifdstream(fds[0])))); 299 } 300 } 301 302 303 /// Helper function for fork(). 304 /// 305 /// Please note: if you update this function to change the return type or to 306 /// raise different errors, do not forget to update fork() accordingly. 307 /// 308 /// \param stdout_file The name of the file in which to store the stdout. 309 /// If this has the magic value /dev/stdout, then the parent's stdout is 310 /// reused without applying any redirection. 311 /// \param stderr_file The name of the file in which to store the stderr. 312 /// If this has the magic value /dev/stderr, then the parent's stderr is 313 /// reused without applying any redirection. 314 /// 315 /// \return In the case of the parent, a new child object returned as a 316 /// dynamically-allocated object because children classes are unique and thus 317 /// noncopyable. In the case of the child, a NULL pointer. 318 /// 319 /// \throw process::system_error If the call to fork(2) fails. 320 std::auto_ptr< process::child > 321 process::child::fork_files_aux(const fs::path& stdout_file, 322 const fs::path& stderr_file) 323 { 324 std::cout.flush(); 325 std::cerr.flush(); 326 327 std::auto_ptr< signals::interrupts_inhibiter > inhibiter( 328 new signals::interrupts_inhibiter); 329 pid_t pid = detail::syscall_fork(); 330 if (pid == -1) { 331 inhibiter.reset(NULL); // Unblock signals. 332 throw process::system_error("fork(2) failed", errno); 333 } else if (pid == 0) { 334 inhibiter.reset(NULL); // Unblock signals. 335 #if !defined(__minix) 336 ::setpgid(::getpid(), ::getpid()); 337 #endif /* !defined(__minix) */ 338 339 try { 340 if (stdout_file != fs::path("/dev/stdout")) { 341 const int stdout_fd = open_for_append(stdout_file); 342 safe_dup(stdout_fd, STDOUT_FILENO); 343 ::close(stdout_fd); 344 } 345 if (stderr_file != fs::path("/dev/stderr")) { 346 const int stderr_fd = open_for_append(stderr_file); 347 safe_dup(stderr_fd, STDERR_FILENO); 348 ::close(stderr_fd); 349 } 350 } catch (const system_error& e) { 351 std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); 352 std::abort(); 353 } 354 return std::auto_ptr< process::child >(NULL); 355 } else { 356 LD(F("Spawned process %s: stdout=%s, stderr=%s") % pid % stdout_file % 357 stderr_file); 358 signals::add_pid_to_kill(pid); 359 inhibiter.reset(NULL); // Unblock signals. 360 return std::auto_ptr< process::child >( 361 new process::child(new impl(pid, NULL))); 362 } 363 } 364 365 366 /// Spawns a new binary and multiplexes and captures its stdout and stderr. 367 /// 368 /// If the subprocess cannot be completely set up for any reason, it attempts to 369 /// dump an error message to its stderr channel and it then calls std::abort(). 370 /// 371 /// \param program The binary to execute. 372 /// \param args The arguments to pass to the binary, without the program name. 373 /// 374 /// \return A new child object, returned as a dynamically-allocated object 375 /// because children classes are unique and thus noncopyable. 376 /// 377 /// \throw process::system_error If the process cannot be spawned due to a 378 /// system call error. 379 std::auto_ptr< process::child > 380 process::child::spawn_capture(const fs::path& program, const args_vector& args) 381 { 382 std::auto_ptr< child > child = fork_capture_aux(); 383 if (child.get() == NULL) 384 cxx_exec(program, args); 385 log_exec(program, args); 386 return child; 387 } 388 389 390 /// Spawns a new binary and redirects its stdout and stderr to files. 391 /// 392 /// If the subprocess cannot be completely set up for any reason, it attempts to 393 /// dump an error message to its stderr channel and it then calls std::abort(). 394 /// 395 /// \param program The binary to execute. 396 /// \param args The arguments to pass to the binary, without the program name. 397 /// \param stdout_file The name of the file in which to store the stdout. 398 /// \param stderr_file The name of the file in which to store the stderr. 399 /// 400 /// \return A new child object, returned as a dynamically-allocated object 401 /// because children classes are unique and thus noncopyable. 402 /// 403 /// \throw process::system_error If the process cannot be spawned due to a 404 /// system call error. 405 std::auto_ptr< process::child > 406 process::child::spawn_files(const fs::path& program, 407 const args_vector& args, 408 const fs::path& stdout_file, 409 const fs::path& stderr_file) 410 { 411 std::auto_ptr< child > child = fork_files_aux(stdout_file, stderr_file); 412 if (child.get() == NULL) 413 cxx_exec(program, args); 414 log_exec(program, args); 415 return child; 416 } 417 418 419 /// Returns the process identifier of this child. 420 /// 421 /// \return A process identifier. 422 int 423 process::child::pid(void) const 424 { 425 return _pimpl->_pid; 426 } 427 428 429 /// Gets the input stream corresponding to the stdout and stderr of the child. 430 /// 431 /// \pre The child must have been started by fork_capture(). 432 /// 433 /// \return A reference to the input stream connected to the output of the test 434 /// case. 435 std::istream& 436 process::child::output(void) 437 { 438 PRE(_pimpl->_output.get() != NULL); 439 return *_pimpl->_output; 440 } 441 442 443 /// Blocks to wait for completion. 444 /// 445 /// \return The termination status of the child process. 446 /// 447 /// \throw process::system_error If the call to waitpid(2) fails. 448 process::status 449 process::child::wait(void) 450 { 451 const process::status status = safe_wait(_pimpl->_pid); 452 { 453 signals::interrupts_inhibiter inhibiter; 454 signals::remove_pid_to_kill(_pimpl->_pid); 455 } 456 return status; 457 } 458