git: ed080d991586 - main - ptrace_test: add test for the PT_ATTACH behavior on sleeping thread

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 18 Apr 2025 15:33:19 UTC
The branch main has been updated by kib:

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

commit ed080d9915869708a9ab7badc217aff17ebbef6c
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-04-18 12:20:20 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-04-18 15:33:12 +0000

    ptrace_test: add test for the PT_ATTACH behavior on sleeping thread
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential revision:  https://reviews.freebsd.org/D49887
---
 tests/sys/kern/ptrace_test.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c
index de411af6bc40..5dc235eb9200 100644
--- a/tests/sys/kern/ptrace_test.c
+++ b/tests/sys/kern/ptrace_test.c
@@ -28,6 +28,7 @@
 #include <sys/elf.h>
 #include <sys/event.h>
 #include <sys/file.h>
+#include <sys/mman.h>
 #include <sys/time.h>
 #include <sys/procctl.h>
 #include <sys/procdesc.h>
@@ -4464,6 +4465,65 @@ ATF_TC_BODY(ptrace__reap_kill_stopped, tc)
 	REQUIRE_EQ(-1, prk.rk_fpid);
 }
 
+struct child_res {
+	struct timespec sleep_time;
+	int nanosleep_res;
+	int nanosleep_errno;
+};
+
+static const long nsec = 1000000000L;
+static const struct timespec ten_sec = {
+	.tv_sec = 10,
+	.tv_nsec = 0,
+};
+static const struct timespec twelve_sec = {
+	.tv_sec = 12,
+	.tv_nsec = 0,
+};
+
+ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_no_EINTR);
+ATF_TC_BODY(ptrace__PT_ATTACH_no_EINTR, tc)
+{
+	struct child_res *shm;
+	struct timespec rqt, now, wake;
+	pid_t debuggee;
+	int status;
+
+	shm = mmap(NULL, sizeof(*shm), PROT_READ | PROT_WRITE,
+	    MAP_SHARED | MAP_ANON, -1, 0);
+	ATF_REQUIRE(shm != MAP_FAILED);
+
+	ATF_REQUIRE((debuggee = fork()) != -1);
+	if (debuggee == 0) {
+		rqt.tv_sec = 10;
+		rqt.tv_nsec = 0;
+		clock_gettime(CLOCK_MONOTONIC_PRECISE, &now);
+		errno = 0;
+		shm->nanosleep_res = nanosleep(&rqt, NULL);
+		shm->nanosleep_errno = errno;
+		clock_gettime(CLOCK_MONOTONIC_PRECISE, &wake);
+		timespecsub(&wake, &now, &shm->sleep_time);
+		_exit(0);
+	}
+
+	/* Give the debuggee some time to go to sleep. */
+	sleep(2);
+	REQUIRE_EQ(ptrace(PT_ATTACH, debuggee, 0, 0), 0);
+	REQUIRE_EQ(waitpid(debuggee, &status, 0), debuggee);
+	ATF_REQUIRE(WIFSTOPPED(status));
+	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);
+
+	REQUIRE_EQ(ptrace(PT_DETACH, debuggee, 0, 0), 0);
+	REQUIRE_EQ(waitpid(debuggee, &status, 0), debuggee);
+	ATF_REQUIRE(WIFEXITED(status));
+	REQUIRE_EQ(WEXITSTATUS(status), 0);
+
+	ATF_REQUIRE(shm->nanosleep_res == 0);
+	ATF_REQUIRE(shm->nanosleep_errno == 0);
+	ATF_REQUIRE(timespeccmp(&shm->sleep_time, &ten_sec, >=));
+	ATF_REQUIRE(timespeccmp(&shm->sleep_time, &twelve_sec, <=));
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
@@ -4532,6 +4592,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child);
 	ATF_TP_ADD_TC(tp, ptrace__PT_SC_REMOTE_getpid);
 	ATF_TP_ADD_TC(tp, ptrace__reap_kill_stopped);
+	ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_no_EINTR);
 
 	return (atf_no_error());
 }