git: c0946aee5b2a - main - libc tests: Add some test cases for recursive exiting

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Wed, 07 Aug 2024 16:08:39 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0946aee5b2ab6c9bb2e8281a1f625914ed2fec8

commit c0946aee5b2ab6c9bb2e8281a1f625914ed2fec8
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-07 16:06:11 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-08-07 16:06:11 +0000

    libc tests: Add some test cases for recursive exiting
    
    Derived from tests posted by kib in D46108.  I made one of them use a
    pthread barrier instead of sleeping.
    
    Reviewed by:    kib
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D46176
---
 lib/libc/tests/stdlib/Makefile         |  1 +
 lib/libc/tests/stdlib/libc_exit_test.c | 69 ++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile
index 29cf895006d1..6f57b8014a1e 100644
--- a/lib/libc/tests/stdlib/Makefile
+++ b/lib/libc/tests/stdlib/Makefile
@@ -75,6 +75,7 @@ LDFLAGS.$t+=	-L${LIBNETBSD_OBJDIR}
 LIBADD.${t}+=	netbsd util
 .endfor
 
+LIBADD.libc_exit_test+=		pthread
 LIBADD.strtod_test+=		m
 
 SUBDIR+=	dynthr_mod
diff --git a/lib/libc/tests/stdlib/libc_exit_test.c b/lib/libc/tests/stdlib/libc_exit_test.c
index c47d03d1d598..12965261bdb3 100644
--- a/lib/libc/tests/stdlib/libc_exit_test.c
+++ b/lib/libc/tests/stdlib/libc_exit_test.c
@@ -6,6 +6,7 @@
 
 #include <sys/wait.h>
 
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -78,8 +79,76 @@ ATF_TC_BODY(quick_exit, tc)
 	ATF_CHECK_STREQ("hello, abc", buf);
 }
 
+static void
+myatexit1(void)
+{
+	exit(12);
+}
+
+ATF_TC_WITHOUT_HEAD(recursive_exit1);
+ATF_TC_BODY(recursive_exit1, tc)
+{
+	pid_t pid;
+	int wstatus;
+
+	pid = fork();
+	if (pid == 0) {
+		atexit(myatexit1);
+		exit(1);
+	}
+	ATF_REQUIRE_MSG(pid > 0,
+	    "expect fork() to succeed");
+	ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0),
+	    "expect to collect child process");
+	ATF_CHECK(WIFEXITED(wstatus));
+	ATF_CHECK_EQ(WEXITSTATUS(wstatus), 12);
+}
+
+static pthread_barrier_t barrier;
+
+static void
+myatexit2(void)
+{
+	pthread_barrier_wait(&barrier);
+	exit(12);
+}
+
+static void *
+mythreadexit(void *arg)
+{
+	pthread_barrier_wait(&barrier);
+	exit(15);
+}
+
+ATF_TC_WITHOUT_HEAD(recursive_exit2);
+ATF_TC_BODY(recursive_exit2, tc)
+{
+	pid_t pid;
+	int wstatus;
+
+	pid = fork();
+	if (pid == 0) {
+		pthread_t thr;
+
+		atexit(myatexit2);
+
+		pthread_barrier_init(&barrier, NULL, 2);
+		pthread_create(&thr, NULL, mythreadexit, NULL);
+
+		exit(1);
+	}
+	ATF_REQUIRE_MSG(pid > 0,
+	    "expect fork() to succeed");
+	ATF_CHECK_EQ_MSG(pid, waitpid(pid, &wstatus, 0),
+	    "expect to collect child process");
+	ATF_CHECK(WIFEXITED(wstatus));
+	ATF_CHECK_EQ(WEXITSTATUS(wstatus), 12);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, quick_exit);
+	ATF_TP_ADD_TC(tp, recursive_exit1);
+	ATF_TP_ADD_TC(tp, recursive_exit2);
 	return (atf_no_error());
 }