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