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 31extern "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 58namespace utils { 59namespace process { 60 61 62/// Private implementation fields for child objects. 63struct 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 83namespace fs = utils::fs; 84namespace process = utils::process; 85namespace signals = utils::signals; 86 87 88namespace { 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. 98static void 99safe_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. 116static int 117open_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. 142static process::status 143safe_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. 160static void 161log_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 179static 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. 194static void 195cxx_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. 233process::child::child(impl *implptr) : 234 _pimpl(implptr) 235{ 236} 237 238 239/// Destructor for child. 240process::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. 255std::unique_ptr< process::child > 256process::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. 315std::unique_ptr< process::child > 316process::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. 372std::unique_ptr< process::child > 373process::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. 398std::unique_ptr< process::child > 399process::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. 415int 416process::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. 428std::istream& 429process::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. 441process::status 442process::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