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