1 /*- 2 * Copyright (c) 2023 Klara, Inc. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/wait.h> 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 13 #include <atf-c.h> 14 15 static void func_a(void) 16 { 17 if (write(STDOUT_FILENO, "a", 1) != 1) 18 _Exit(1); 19 } 20 21 static void func_b(void) 22 { 23 if (write(STDOUT_FILENO, "b", 1) != 1) 24 _Exit(1); 25 } 26 27 static void func_c(void) 28 { 29 if (write(STDOUT_FILENO, "c", 1) != 1) 30 _Exit(1); 31 } 32 33 static void child(void) 34 { 35 // this will be received by the parent 36 printf("hello, "); 37 fflush(stdout); 38 // this won't, because quick_exit() does not flush 39 printf("world"); 40 // these will be called in reverse order, producing "abc" 41 if (at_quick_exit(func_c) != 0 || 42 at_quick_exit(func_b) != 0 || 43 at_quick_exit(func_a) != 0) 44 _Exit(1); 45 quick_exit(0); 46 } 47 48 ATF_TC_WITHOUT_HEAD(quick_exit); 49 ATF_TC_BODY(quick_exit, tc) 50 { 51 char buf[100] = ""; 52 ssize_t len; 53 int p[2], wstatus = 0; 54 pid_t pid; 55 56 ATF_REQUIRE(pipe(p) == 0); 57 pid = fork(); 58 if (pid == 0) { 59 if (dup2(p[1], STDOUT_FILENO) < 0) 60 _Exit(1); 61 (void)close(p[1]); 62 (void)close(p[0]); 63 child(); 64 _Exit(1); 65 } 66 ATF_REQUIRE_MSG(pid > 0, 67 "expect fork() to succeed"); 68 ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0), 69 "expect to collect child process"); 70 ATF_CHECK_EQ_MSG(0, wstatus, 71 "expect child to exit cleanly"); 72 ATF_CHECK_MSG((len = read(p[0], buf, sizeof(buf))) > 0, 73 "expect to receive output from child"); 74 ATF_CHECK_STREQ("hello, abc", buf); 75 } 76 77 ATF_TP_ADD_TCS(tp) 78 { 79 ATF_TP_ADD_TC(tp, quick_exit); 80 return (atf_no_error()); 81 } 82