1*b0d29bc4SBrooks Davis // Copyright 2014 The Kyua Authors. 2*b0d29bc4SBrooks Davis // All rights reserved. 3*b0d29bc4SBrooks Davis // 4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without 5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are 6*b0d29bc4SBrooks Davis // met: 7*b0d29bc4SBrooks Davis // 8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright 9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer. 10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright 11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the 12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution. 13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors 14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software 15*b0d29bc4SBrooks Davis // without specific prior written permission. 16*b0d29bc4SBrooks Davis // 17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*b0d29bc4SBrooks Davis 29*b0d29bc4SBrooks Davis #include "utils/process/operations.hpp" 30*b0d29bc4SBrooks Davis 31*b0d29bc4SBrooks Davis extern "C" { 32*b0d29bc4SBrooks Davis #include <sys/types.h> 33*b0d29bc4SBrooks Davis #include <sys/wait.h> 34*b0d29bc4SBrooks Davis 35*b0d29bc4SBrooks Davis #include <signal.h> 36*b0d29bc4SBrooks Davis #include <unistd.h> 37*b0d29bc4SBrooks Davis } 38*b0d29bc4SBrooks Davis 39*b0d29bc4SBrooks Davis #include <cerrno> 40*b0d29bc4SBrooks Davis #include <iostream> 41*b0d29bc4SBrooks Davis 42*b0d29bc4SBrooks Davis #include <atf-c++.hpp> 43*b0d29bc4SBrooks Davis 44*b0d29bc4SBrooks Davis #include "utils/defs.hpp" 45*b0d29bc4SBrooks Davis #include "utils/format/containers.ipp" 46*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp" 47*b0d29bc4SBrooks Davis #include "utils/process/child.ipp" 48*b0d29bc4SBrooks Davis #include "utils/process/exceptions.hpp" 49*b0d29bc4SBrooks Davis #include "utils/process/status.hpp" 50*b0d29bc4SBrooks Davis #include "utils/stacktrace.hpp" 51*b0d29bc4SBrooks Davis #include "utils/test_utils.ipp" 52*b0d29bc4SBrooks Davis 53*b0d29bc4SBrooks Davis namespace fs = utils::fs; 54*b0d29bc4SBrooks Davis namespace process = utils::process; 55*b0d29bc4SBrooks Davis 56*b0d29bc4SBrooks Davis 57*b0d29bc4SBrooks Davis namespace { 58*b0d29bc4SBrooks Davis 59*b0d29bc4SBrooks Davis 60*b0d29bc4SBrooks Davis /// Type of the process::exec() and process::exec_unsafe() functions. 61*b0d29bc4SBrooks Davis typedef void (*exec_function)(const fs::path&, const process::args_vector&); 62*b0d29bc4SBrooks Davis 63*b0d29bc4SBrooks Davis 64*b0d29bc4SBrooks Davis /// Calculates the path to the test helpers binary. 65*b0d29bc4SBrooks Davis /// 66*b0d29bc4SBrooks Davis /// \param tc A pointer to the caller test case, needed to extract the value of 67*b0d29bc4SBrooks Davis /// the "srcdir" property. 68*b0d29bc4SBrooks Davis /// 69*b0d29bc4SBrooks Davis /// \return The path to the helpers binary. 70*b0d29bc4SBrooks Davis static fs::path 71*b0d29bc4SBrooks Davis get_helpers(const atf::tests::tc* tc) 72*b0d29bc4SBrooks Davis { 73*b0d29bc4SBrooks Davis return fs::path(tc->get_config_var("srcdir")) / "helpers"; 74*b0d29bc4SBrooks Davis } 75*b0d29bc4SBrooks Davis 76*b0d29bc4SBrooks Davis 77*b0d29bc4SBrooks Davis /// Body for a subprocess that runs exec(). 78*b0d29bc4SBrooks Davis class child_exec { 79*b0d29bc4SBrooks Davis /// Function to do the exec. 80*b0d29bc4SBrooks Davis const exec_function _do_exec; 81*b0d29bc4SBrooks Davis 82*b0d29bc4SBrooks Davis /// Path to the binary to exec. 83*b0d29bc4SBrooks Davis const fs::path& _program; 84*b0d29bc4SBrooks Davis 85*b0d29bc4SBrooks Davis /// Arguments to the binary, not including argv[0]. 86*b0d29bc4SBrooks Davis const process::args_vector& _args; 87*b0d29bc4SBrooks Davis 88*b0d29bc4SBrooks Davis public: 89*b0d29bc4SBrooks Davis /// Constructor. 90*b0d29bc4SBrooks Davis /// 91*b0d29bc4SBrooks Davis /// \param do_exec Function to do the exec. 92*b0d29bc4SBrooks Davis /// \param program Path to the binary to exec. 93*b0d29bc4SBrooks Davis /// \param args Arguments to the binary, not including argv[0]. 94*b0d29bc4SBrooks Davis child_exec(const exec_function do_exec, const fs::path& program, 95*b0d29bc4SBrooks Davis const process::args_vector& args) : 96*b0d29bc4SBrooks Davis _do_exec(do_exec), _program(program), _args(args) 97*b0d29bc4SBrooks Davis { 98*b0d29bc4SBrooks Davis } 99*b0d29bc4SBrooks Davis 100*b0d29bc4SBrooks Davis /// Body for the subprocess. 101*b0d29bc4SBrooks Davis void 102*b0d29bc4SBrooks Davis operator()(void) 103*b0d29bc4SBrooks Davis { 104*b0d29bc4SBrooks Davis _do_exec(_program, _args); 105*b0d29bc4SBrooks Davis } 106*b0d29bc4SBrooks Davis }; 107*b0d29bc4SBrooks Davis 108*b0d29bc4SBrooks Davis 109*b0d29bc4SBrooks Davis /// Body for a process that returns a specific exit code. 110*b0d29bc4SBrooks Davis /// 111*b0d29bc4SBrooks Davis /// \tparam ExitStatus The exit status for the subprocess. 112*b0d29bc4SBrooks Davis template< int ExitStatus > 113*b0d29bc4SBrooks Davis static void 114*b0d29bc4SBrooks Davis child_exit(void) 115*b0d29bc4SBrooks Davis { 116*b0d29bc4SBrooks Davis std::exit(ExitStatus); 117*b0d29bc4SBrooks Davis } 118*b0d29bc4SBrooks Davis 119*b0d29bc4SBrooks Davis 120*b0d29bc4SBrooks Davis static void suspend(void) UTILS_NORETURN; 121*b0d29bc4SBrooks Davis 122*b0d29bc4SBrooks Davis 123*b0d29bc4SBrooks Davis /// Blocks a subprocess from running indefinitely. 124*b0d29bc4SBrooks Davis static void 125*b0d29bc4SBrooks Davis suspend(void) 126*b0d29bc4SBrooks Davis { 127*b0d29bc4SBrooks Davis sigset_t mask; 128*b0d29bc4SBrooks Davis sigemptyset(&mask); 129*b0d29bc4SBrooks Davis for (;;) { 130*b0d29bc4SBrooks Davis ::sigsuspend(&mask); 131*b0d29bc4SBrooks Davis } 132*b0d29bc4SBrooks Davis } 133*b0d29bc4SBrooks Davis 134*b0d29bc4SBrooks Davis 135*b0d29bc4SBrooks Davis static void write_loop(const int) UTILS_NORETURN; 136*b0d29bc4SBrooks Davis 137*b0d29bc4SBrooks Davis 138*b0d29bc4SBrooks Davis /// Provides an infinite stream of data in a subprocess. 139*b0d29bc4SBrooks Davis /// 140*b0d29bc4SBrooks Davis /// \param fd Descriptor into which to write. 141*b0d29bc4SBrooks Davis static void 142*b0d29bc4SBrooks Davis write_loop(const int fd) 143*b0d29bc4SBrooks Davis { 144*b0d29bc4SBrooks Davis const int cookie = 0x12345678; 145*b0d29bc4SBrooks Davis for (;;) { 146*b0d29bc4SBrooks Davis std::cerr << "Still alive in PID " << ::getpid() << '\n'; 147*b0d29bc4SBrooks Davis if (::write(fd, &cookie, sizeof(cookie)) != sizeof(cookie)) 148*b0d29bc4SBrooks Davis std::exit(EXIT_FAILURE); 149*b0d29bc4SBrooks Davis ::sleep(1); 150*b0d29bc4SBrooks Davis } 151*b0d29bc4SBrooks Davis } 152*b0d29bc4SBrooks Davis 153*b0d29bc4SBrooks Davis 154*b0d29bc4SBrooks Davis } // anonymous namespace 155*b0d29bc4SBrooks Davis 156*b0d29bc4SBrooks Davis 157*b0d29bc4SBrooks Davis /// Tests an exec function with no arguments. 158*b0d29bc4SBrooks Davis /// 159*b0d29bc4SBrooks Davis /// \param tc The calling test case. 160*b0d29bc4SBrooks Davis /// \param do_exec The exec function to test. 161*b0d29bc4SBrooks Davis static void 162*b0d29bc4SBrooks Davis check_exec_no_args(const atf::tests::tc* tc, const exec_function do_exec) 163*b0d29bc4SBrooks Davis { 164*b0d29bc4SBrooks Davis std::auto_ptr< process::child > child = process::child::fork_files( 165*b0d29bc4SBrooks Davis child_exec(do_exec, get_helpers(tc), process::args_vector()), 166*b0d29bc4SBrooks Davis fs::path("stdout"), fs::path("stderr")); 167*b0d29bc4SBrooks Davis const process::status status = child->wait(); 168*b0d29bc4SBrooks Davis ATF_REQUIRE(status.exited()); 169*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(EXIT_FAILURE, status.exitstatus()); 170*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_file("Must provide a helper name", "stderr")); 171*b0d29bc4SBrooks Davis } 172*b0d29bc4SBrooks Davis 173*b0d29bc4SBrooks Davis 174*b0d29bc4SBrooks Davis /// Tests an exec function with some arguments. 175*b0d29bc4SBrooks Davis /// 176*b0d29bc4SBrooks Davis /// \param tc The calling test case. 177*b0d29bc4SBrooks Davis /// \param do_exec The exec function to test. 178*b0d29bc4SBrooks Davis static void 179*b0d29bc4SBrooks Davis check_exec_some_args(const atf::tests::tc* tc, const exec_function do_exec) 180*b0d29bc4SBrooks Davis { 181*b0d29bc4SBrooks Davis process::args_vector args; 182*b0d29bc4SBrooks Davis args.push_back("print-args"); 183*b0d29bc4SBrooks Davis args.push_back("foo"); 184*b0d29bc4SBrooks Davis args.push_back("bar"); 185*b0d29bc4SBrooks Davis 186*b0d29bc4SBrooks Davis std::auto_ptr< process::child > child = process::child::fork_files( 187*b0d29bc4SBrooks Davis child_exec(do_exec, get_helpers(tc), args), 188*b0d29bc4SBrooks Davis fs::path("stdout"), fs::path("stderr")); 189*b0d29bc4SBrooks Davis const process::status status = child->wait(); 190*b0d29bc4SBrooks Davis ATF_REQUIRE(status.exited()); 191*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); 192*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_file("argv\\[1\\] = print-args", "stdout")); 193*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_file("argv\\[2\\] = foo", "stdout")); 194*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_file("argv\\[3\\] = bar", "stdout")); 195*b0d29bc4SBrooks Davis } 196*b0d29bc4SBrooks Davis 197*b0d29bc4SBrooks Davis 198*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec__no_args); 199*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec__no_args) 200*b0d29bc4SBrooks Davis { 201*b0d29bc4SBrooks Davis check_exec_no_args(this, process::exec); 202*b0d29bc4SBrooks Davis } 203*b0d29bc4SBrooks Davis 204*b0d29bc4SBrooks Davis 205*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec__some_args); 206*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec__some_args) 207*b0d29bc4SBrooks Davis { 208*b0d29bc4SBrooks Davis check_exec_some_args(this, process::exec); 209*b0d29bc4SBrooks Davis } 210*b0d29bc4SBrooks Davis 211*b0d29bc4SBrooks Davis 212*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec__fail); 213*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec__fail) 214*b0d29bc4SBrooks Davis { 215*b0d29bc4SBrooks Davis utils::avoid_coredump_on_crash(); 216*b0d29bc4SBrooks Davis 217*b0d29bc4SBrooks Davis std::auto_ptr< process::child > child = process::child::fork_files( 218*b0d29bc4SBrooks Davis child_exec(process::exec, fs::path("non-existent"), 219*b0d29bc4SBrooks Davis process::args_vector()), 220*b0d29bc4SBrooks Davis fs::path("stdout"), fs::path("stderr")); 221*b0d29bc4SBrooks Davis const process::status status = child->wait(); 222*b0d29bc4SBrooks Davis ATF_REQUIRE(status.signaled()); 223*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(SIGABRT, status.termsig()); 224*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_file("Failed to execute non-existent", 225*b0d29bc4SBrooks Davis "stderr")); 226*b0d29bc4SBrooks Davis } 227*b0d29bc4SBrooks Davis 228*b0d29bc4SBrooks Davis 229*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec_unsafe__no_args); 230*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec_unsafe__no_args) 231*b0d29bc4SBrooks Davis { 232*b0d29bc4SBrooks Davis check_exec_no_args(this, process::exec_unsafe); 233*b0d29bc4SBrooks Davis } 234*b0d29bc4SBrooks Davis 235*b0d29bc4SBrooks Davis 236*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec_unsafe__some_args); 237*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec_unsafe__some_args) 238*b0d29bc4SBrooks Davis { 239*b0d29bc4SBrooks Davis check_exec_some_args(this, process::exec_unsafe); 240*b0d29bc4SBrooks Davis } 241*b0d29bc4SBrooks Davis 242*b0d29bc4SBrooks Davis 243*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(exec_unsafe__fail); 244*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(exec_unsafe__fail) 245*b0d29bc4SBrooks Davis { 246*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW_RE( 247*b0d29bc4SBrooks Davis process::system_error, "Failed to execute missing-program", 248*b0d29bc4SBrooks Davis process::exec_unsafe(fs::path("missing-program"), 249*b0d29bc4SBrooks Davis process::args_vector())); 250*b0d29bc4SBrooks Davis } 251*b0d29bc4SBrooks Davis 252*b0d29bc4SBrooks Davis 253*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(terminate_group__setpgrp_executed); 254*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(terminate_group__setpgrp_executed) 255*b0d29bc4SBrooks Davis { 256*b0d29bc4SBrooks Davis int first_fds[2], second_fds[2]; 257*b0d29bc4SBrooks Davis ATF_REQUIRE(::pipe(first_fds) != -1); 258*b0d29bc4SBrooks Davis ATF_REQUIRE(::pipe(second_fds) != -1); 259*b0d29bc4SBrooks Davis 260*b0d29bc4SBrooks Davis const pid_t pid = ::fork(); 261*b0d29bc4SBrooks Davis ATF_REQUIRE(pid != -1); 262*b0d29bc4SBrooks Davis if (pid == 0) { 263*b0d29bc4SBrooks Davis ::setpgid(::getpid(), ::getpid()); 264*b0d29bc4SBrooks Davis const pid_t pid2 = ::fork(); 265*b0d29bc4SBrooks Davis if (pid2 == -1) { 266*b0d29bc4SBrooks Davis std::exit(EXIT_FAILURE); 267*b0d29bc4SBrooks Davis } else if (pid2 == 0) { 268*b0d29bc4SBrooks Davis ::close(first_fds[0]); 269*b0d29bc4SBrooks Davis ::close(first_fds[1]); 270*b0d29bc4SBrooks Davis ::close(second_fds[0]); 271*b0d29bc4SBrooks Davis write_loop(second_fds[1]); 272*b0d29bc4SBrooks Davis } 273*b0d29bc4SBrooks Davis ::close(first_fds[0]); 274*b0d29bc4SBrooks Davis ::close(second_fds[0]); 275*b0d29bc4SBrooks Davis ::close(second_fds[1]); 276*b0d29bc4SBrooks Davis write_loop(first_fds[1]); 277*b0d29bc4SBrooks Davis } 278*b0d29bc4SBrooks Davis ::close(first_fds[1]); 279*b0d29bc4SBrooks Davis ::close(second_fds[1]); 280*b0d29bc4SBrooks Davis 281*b0d29bc4SBrooks Davis int dummy; 282*b0d29bc4SBrooks Davis std::cerr << "Waiting for children to start\n"; 283*b0d29bc4SBrooks Davis while (::read(first_fds[0], &dummy, sizeof(dummy)) <= 0 || 284*b0d29bc4SBrooks Davis ::read(second_fds[0], &dummy, sizeof(dummy)) <= 0) { 285*b0d29bc4SBrooks Davis // Wait for children to come up. 286*b0d29bc4SBrooks Davis } 287*b0d29bc4SBrooks Davis 288*b0d29bc4SBrooks Davis process::terminate_group(pid); 289*b0d29bc4SBrooks Davis std::cerr << "Waiting for children to die\n"; 290*b0d29bc4SBrooks Davis while (::read(first_fds[0], &dummy, sizeof(dummy)) > 0 || 291*b0d29bc4SBrooks Davis ::read(second_fds[0], &dummy, sizeof(dummy)) > 0) { 292*b0d29bc4SBrooks Davis // Wait for children to terminate. If they don't, then the test case 293*b0d29bc4SBrooks Davis // will time out. 294*b0d29bc4SBrooks Davis } 295*b0d29bc4SBrooks Davis 296*b0d29bc4SBrooks Davis int status; 297*b0d29bc4SBrooks Davis ATF_REQUIRE(::wait(&status) != -1); 298*b0d29bc4SBrooks Davis ATF_REQUIRE(WIFSIGNALED(status)); 299*b0d29bc4SBrooks Davis ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 300*b0d29bc4SBrooks Davis } 301*b0d29bc4SBrooks Davis 302*b0d29bc4SBrooks Davis 303*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(terminate_group__setpgrp_not_executed); 304*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(terminate_group__setpgrp_not_executed) 305*b0d29bc4SBrooks Davis { 306*b0d29bc4SBrooks Davis const pid_t pid = ::fork(); 307*b0d29bc4SBrooks Davis ATF_REQUIRE(pid != -1); 308*b0d29bc4SBrooks Davis if (pid == 0) { 309*b0d29bc4SBrooks Davis // We do not call setgprp() here to simulate the race that happens when 310*b0d29bc4SBrooks Davis // we invoke terminate_group on a process that has not yet had a chance 311*b0d29bc4SBrooks Davis // to run the setpgrp() call. 312*b0d29bc4SBrooks Davis suspend(); 313*b0d29bc4SBrooks Davis } 314*b0d29bc4SBrooks Davis 315*b0d29bc4SBrooks Davis process::terminate_group(pid); 316*b0d29bc4SBrooks Davis 317*b0d29bc4SBrooks Davis int status; 318*b0d29bc4SBrooks Davis ATF_REQUIRE(::wait(&status) != -1); 319*b0d29bc4SBrooks Davis ATF_REQUIRE(WIFSIGNALED(status)); 320*b0d29bc4SBrooks Davis ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 321*b0d29bc4SBrooks Davis } 322*b0d29bc4SBrooks Davis 323*b0d29bc4SBrooks Davis 324*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(terminate_self_with__exitstatus); 325*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(terminate_self_with__exitstatus) 326*b0d29bc4SBrooks Davis { 327*b0d29bc4SBrooks Davis const pid_t pid = ::fork(); 328*b0d29bc4SBrooks Davis ATF_REQUIRE(pid != -1); 329*b0d29bc4SBrooks Davis if (pid == 0) { 330*b0d29bc4SBrooks Davis const process::status status = process::status::fake_exited(123); 331*b0d29bc4SBrooks Davis process::terminate_self_with(status); 332*b0d29bc4SBrooks Davis } 333*b0d29bc4SBrooks Davis 334*b0d29bc4SBrooks Davis int status; 335*b0d29bc4SBrooks Davis ATF_REQUIRE(::wait(&status) != -1); 336*b0d29bc4SBrooks Davis ATF_REQUIRE(WIFEXITED(status)); 337*b0d29bc4SBrooks Davis ATF_REQUIRE(WEXITSTATUS(status) == 123); 338*b0d29bc4SBrooks Davis } 339*b0d29bc4SBrooks Davis 340*b0d29bc4SBrooks Davis 341*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(terminate_self_with__termsig); 342*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(terminate_self_with__termsig) 343*b0d29bc4SBrooks Davis { 344*b0d29bc4SBrooks Davis const pid_t pid = ::fork(); 345*b0d29bc4SBrooks Davis ATF_REQUIRE(pid != -1); 346*b0d29bc4SBrooks Davis if (pid == 0) { 347*b0d29bc4SBrooks Davis const process::status status = process::status::fake_signaled( 348*b0d29bc4SBrooks Davis SIGKILL, false); 349*b0d29bc4SBrooks Davis process::terminate_self_with(status); 350*b0d29bc4SBrooks Davis } 351*b0d29bc4SBrooks Davis 352*b0d29bc4SBrooks Davis int status; 353*b0d29bc4SBrooks Davis ATF_REQUIRE(::wait(&status) != -1); 354*b0d29bc4SBrooks Davis ATF_REQUIRE(WIFSIGNALED(status)); 355*b0d29bc4SBrooks Davis ATF_REQUIRE(WTERMSIG(status) == SIGKILL); 356*b0d29bc4SBrooks Davis ATF_REQUIRE(!WCOREDUMP(status)); 357*b0d29bc4SBrooks Davis } 358*b0d29bc4SBrooks Davis 359*b0d29bc4SBrooks Davis 360*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(terminate_self_with__termsig_and_core); 361*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(terminate_self_with__termsig_and_core) 362*b0d29bc4SBrooks Davis { 363*b0d29bc4SBrooks Davis utils::prepare_coredump_test(this); 364*b0d29bc4SBrooks Davis 365*b0d29bc4SBrooks Davis const pid_t pid = ::fork(); 366*b0d29bc4SBrooks Davis ATF_REQUIRE(pid != -1); 367*b0d29bc4SBrooks Davis if (pid == 0) { 368*b0d29bc4SBrooks Davis const process::status status = process::status::fake_signaled( 369*b0d29bc4SBrooks Davis SIGABRT, true); 370*b0d29bc4SBrooks Davis process::terminate_self_with(status); 371*b0d29bc4SBrooks Davis } 372*b0d29bc4SBrooks Davis 373*b0d29bc4SBrooks Davis int status; 374*b0d29bc4SBrooks Davis ATF_REQUIRE(::wait(&status) != -1); 375*b0d29bc4SBrooks Davis ATF_REQUIRE(WIFSIGNALED(status)); 376*b0d29bc4SBrooks Davis ATF_REQUIRE(WTERMSIG(status) == SIGABRT); 377*b0d29bc4SBrooks Davis ATF_REQUIRE(WCOREDUMP(status)); 378*b0d29bc4SBrooks Davis } 379*b0d29bc4SBrooks Davis 380*b0d29bc4SBrooks Davis 381*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); 382*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(wait__ok) 383*b0d29bc4SBrooks Davis { 384*b0d29bc4SBrooks Davis std::auto_ptr< process::child > child = process::child::fork_capture( 385*b0d29bc4SBrooks Davis child_exit< 15 >); 386*b0d29bc4SBrooks Davis const pid_t pid = child->pid(); 387*b0d29bc4SBrooks Davis child.reset(); // Ensure there is no conflict between destructor and wait. 388*b0d29bc4SBrooks Davis 389*b0d29bc4SBrooks Davis const process::status status = process::wait(pid); 390*b0d29bc4SBrooks Davis ATF_REQUIRE(status.exited()); 391*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(15, status.exitstatus()); 392*b0d29bc4SBrooks Davis } 393*b0d29bc4SBrooks Davis 394*b0d29bc4SBrooks Davis 395*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(wait__fail); 396*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(wait__fail) 397*b0d29bc4SBrooks Davis { 398*b0d29bc4SBrooks Davis ATF_REQUIRE_THROW(process::system_error, process::wait(1)); 399*b0d29bc4SBrooks Davis } 400*b0d29bc4SBrooks Davis 401*b0d29bc4SBrooks Davis 402*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(wait_any__one); 403*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(wait_any__one) 404*b0d29bc4SBrooks Davis { 405*b0d29bc4SBrooks Davis process::child::fork_capture(child_exit< 15 >); 406*b0d29bc4SBrooks Davis 407*b0d29bc4SBrooks Davis const process::status status = process::wait_any(); 408*b0d29bc4SBrooks Davis ATF_REQUIRE(status.exited()); 409*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(15, status.exitstatus()); 410*b0d29bc4SBrooks Davis } 411*b0d29bc4SBrooks Davis 412*b0d29bc4SBrooks Davis 413*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(wait_any__many); 414*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(wait_any__many) 415*b0d29bc4SBrooks Davis { 416*b0d29bc4SBrooks Davis process::child::fork_capture(child_exit< 15 >); 417*b0d29bc4SBrooks Davis process::child::fork_capture(child_exit< 30 >); 418*b0d29bc4SBrooks Davis process::child::fork_capture(child_exit< 45 >); 419*b0d29bc4SBrooks Davis 420*b0d29bc4SBrooks Davis std::set< int > exit_codes; 421*b0d29bc4SBrooks Davis for (int i = 0; i < 3; i++) { 422*b0d29bc4SBrooks Davis const process::status status = process::wait_any(); 423*b0d29bc4SBrooks Davis ATF_REQUIRE(status.exited()); 424*b0d29bc4SBrooks Davis exit_codes.insert(status.exitstatus()); 425*b0d29bc4SBrooks Davis } 426*b0d29bc4SBrooks Davis 427*b0d29bc4SBrooks Davis std::set< int > exp_exit_codes; 428*b0d29bc4SBrooks Davis exp_exit_codes.insert(15); 429*b0d29bc4SBrooks Davis exp_exit_codes.insert(30); 430*b0d29bc4SBrooks Davis exp_exit_codes.insert(45); 431*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_exit_codes, exit_codes); 432*b0d29bc4SBrooks Davis } 433*b0d29bc4SBrooks Davis 434*b0d29bc4SBrooks Davis 435*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(wait_any__none_is_failure); 436*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(wait_any__none_is_failure) 437*b0d29bc4SBrooks Davis { 438*b0d29bc4SBrooks Davis try { 439*b0d29bc4SBrooks Davis const process::status status = process::wait_any(); 440*b0d29bc4SBrooks Davis fail("Expected exception but none raised"); 441*b0d29bc4SBrooks Davis } catch (const process::system_error& e) { 442*b0d29bc4SBrooks Davis ATF_REQUIRE(atf::utils::grep_string("Failed to wait", e.what())); 443*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(ECHILD, e.original_errno()); 444*b0d29bc4SBrooks Davis } 445*b0d29bc4SBrooks Davis } 446*b0d29bc4SBrooks Davis 447*b0d29bc4SBrooks Davis 448*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs) 449*b0d29bc4SBrooks Davis { 450*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec__no_args); 451*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec__some_args); 452*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec__fail); 453*b0d29bc4SBrooks Davis 454*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec_unsafe__no_args); 455*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec_unsafe__some_args); 456*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, exec_unsafe__fail); 457*b0d29bc4SBrooks Davis 458*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, terminate_group__setpgrp_executed); 459*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, terminate_group__setpgrp_not_executed); 460*b0d29bc4SBrooks Davis 461*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, terminate_self_with__exitstatus); 462*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, terminate_self_with__termsig); 463*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, terminate_self_with__termsig_and_core); 464*b0d29bc4SBrooks Davis 465*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, wait__ok); 466*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, wait__fail); 467*b0d29bc4SBrooks Davis 468*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, wait_any__one); 469*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, wait_any__many); 470*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, wait_any__none_is_failure); 471*b0d29bc4SBrooks Davis } 472