Path: blob/main/lib/libc/tests/stdlib/libc_exit_test.c
39530 views
/*-1* Copyright (c) 2023 Klara, Inc.2*3* SPDX-License-Identifier: BSD-2-Clause4*/56#include <sys/wait.h>78#include <pthread.h>9#include <stdio.h>10#include <stdlib.h>11#include <unistd.h>1213#include <atf-c.h>1415static void16func_a(void)17{18if (write(STDOUT_FILENO, "a", 1) != 1)19_Exit(1);20}2122static void23func_b(void)24{25if (write(STDOUT_FILENO, "b", 1) != 1)26_Exit(1);27}2829static void30func_c(void)31{32if (write(STDOUT_FILENO, "c", 1) != 1)33_Exit(1);34}3536static void37child(void)38{39/* this will be received by the parent */40printf("hello, ");41fflush(stdout);42/* this won't, because quick_exit() does not flush */43printf("world");44/* these will be called in reverse order, producing "abc" */45if (at_quick_exit(func_c) != 0 ||46at_quick_exit(func_b) != 0 ||47at_quick_exit(func_a) != 0)48_Exit(1);49quick_exit(0);50}5152ATF_TC_WITHOUT_HEAD(quick_exit);53ATF_TC_BODY(quick_exit, tc)54{55char buf[100] = "";56ssize_t len;57int p[2], wstatus = 0;58pid_t pid;5960ATF_REQUIRE(pipe(p) == 0);61pid = fork();62if (pid == 0) {63if (dup2(p[1], STDOUT_FILENO) < 0)64_Exit(1);65(void)close(p[1]);66(void)close(p[0]);67child();68_Exit(1);69}70ATF_REQUIRE_MSG(pid > 0,71"expect fork() to succeed");72ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0),73"expect to collect child process");74ATF_CHECK_EQ_MSG(0, wstatus,75"expect child to exit cleanly");76ATF_CHECK_MSG((len = read(p[0], buf, sizeof(buf))) > 0,77"expect to receive output from child");78ATF_CHECK_STREQ("hello, abc", buf);79}8081static void82myatexit1(void)83{84exit(12);85}8687ATF_TC_WITHOUT_HEAD(recursive_exit1);88ATF_TC_BODY(recursive_exit1, tc)89{90pid_t pid;91int wstatus;9293pid = fork();94if (pid == 0) {95atexit(myatexit1);96exit(1);97}98ATF_REQUIRE_MSG(pid > 0,99"expect fork() to succeed");100ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0),101"expect to collect child process");102ATF_CHECK(WIFEXITED(wstatus));103ATF_CHECK_EQ(WEXITSTATUS(wstatus), 12);104}105106static pthread_barrier_t barrier;107108static void109myatexit2(void)110{111pthread_barrier_wait(&barrier);112exit(12);113}114115static void *116mythreadexit(void *arg)117{118pthread_barrier_wait(&barrier);119exit(15);120}121122ATF_TC_WITHOUT_HEAD(recursive_exit2);123ATF_TC_BODY(recursive_exit2, tc)124{125pid_t pid;126int wstatus;127128pid = fork();129if (pid == 0) {130pthread_t thr;131132atexit(myatexit2);133134pthread_barrier_init(&barrier, NULL, 2);135pthread_create(&thr, NULL, mythreadexit, NULL);136137exit(1);138}139ATF_REQUIRE_MSG(pid > 0,140"expect fork() to succeed");141ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0),142"expect to collect child process");143ATF_CHECK(WIFEXITED(wstatus));144ATF_CHECK_EQ(WEXITSTATUS(wstatus), 12);145}146147ATF_TP_ADD_TCS(tp)148{149ATF_TP_ADD_TC(tp, quick_exit);150ATF_TP_ADD_TC(tp, recursive_exit1);151ATF_TP_ADD_TC(tp, recursive_exit2);152return (atf_no_error());153}154155156