Date: Fri, 12 May 2017 18:02:57 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318246 - head/tests/sys/kern Message-ID: <201705121802.v4CI2vjx057018@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Fri May 12 18:02:57 2017 New Revision: 318246 URL: https://svnweb.freebsd.org/changeset/base/318246 Log: Add a regression test for r318191. Reviewed by: badger MFC after: 1 week Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D10684 Modified: head/tests/sys/kern/ptrace_test.c Modified: head/tests/sys/kern/ptrace_test.c ============================================================================== --- head/tests/sys/kern/ptrace_test.c Fri May 12 18:01:05 2017 (r318245) +++ head/tests/sys/kern/ptrace_test.c Fri May 12 18:02:57 2017 (r318246) @@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/cpuset.h> #include <sys/event.h> +#include <sys/file.h> #include <sys/time.h> #include <sys/procctl.h> #include <sys/ptrace.h> @@ -3025,6 +3026,99 @@ ATF_TC_BODY(ptrace__event_mask_sigkill_d ATF_REQUIRE(errno == ECHILD); } +static void * +flock_thread(void *arg) +{ + int fd; + + fd = *(int *)arg; + (void)flock(fd, LOCK_EX); + (void)flock(fd, LOCK_UN); + return (NULL); +} + +/* + * Verify that PT_ATTACH will suspend threads sleeping in an SBDRY section. + * We rely on the fact that the lockf implementation sets SBDRY before blocking + * on a lock. This is a regression test for r318191. + */ +ATF_TC_WITHOUT_HEAD(ptrace__PT_ATTACH_with_SBDRY_thread); +ATF_TC_BODY(ptrace__PT_ATTACH_with_SBDRY_thread, tc) +{ + pthread_barrier_t barrier; + pthread_barrierattr_t battr; + char tmpfile[64]; + pid_t child, wpid; + int error, fd, i, status; + + ATF_REQUIRE(pthread_barrierattr_init(&battr) == 0); + ATF_REQUIRE(pthread_barrierattr_setpshared(&battr, + PTHREAD_PROCESS_SHARED) == 0); + ATF_REQUIRE(pthread_barrier_init(&barrier, &battr, 2) == 0); + + (void)snprintf(tmpfile, sizeof(tmpfile), "./ptrace.XXXXXX"); + fd = mkstemp(tmpfile); + ATF_REQUIRE(fd >= 0); + + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + pthread_t t[2]; + int error, cfd; + + error = pthread_barrier_wait(&barrier); + if (error != 0 && error != PTHREAD_BARRIER_SERIAL_THREAD) + _exit(1); + + cfd = open(tmpfile, O_RDONLY); + if (cfd < 0) + _exit(1); + + /* + * We want at least two threads blocked on the file lock since + * the SIGSTOP from PT_ATTACH may kick one of them out of + * sleep. + */ + if (pthread_create(&t[0], NULL, flock_thread, &cfd) != 0) + _exit(1); + if (pthread_create(&t[1], NULL, flock_thread, &cfd) != 0) + _exit(1); + if (pthread_join(t[0], NULL) != 0) + _exit(1); + if (pthread_join(t[1], NULL) != 0) + _exit(1); + _exit(0); + } + + ATF_REQUIRE(flock(fd, LOCK_EX) == 0); + + error = pthread_barrier_wait(&barrier); + ATF_REQUIRE(error == 0 || error == PTHREAD_BARRIER_SERIAL_THREAD); + + /* + * Give the child some time to block. Is there a better way to do this? + */ + sleep(1); + + /* + * Attach and give the child 3 seconds to stop. + */ + ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0); + for (i = 0; i < 3; i++) { + wpid = waitpid(child, &status, WNOHANG); + if (wpid == child && WIFSTOPPED(status) && + WSTOPSIG(status) == SIGSTOP) + break; + sleep(1); + } + ATF_REQUIRE_MSG(i < 3, "failed to stop child process after PT_ATTACH"); + + ATF_REQUIRE(ptrace(PT_DETACH, child, NULL, 0) == 0); + + ATF_REQUIRE(flock(fd, LOCK_UN) == 0); + ATF_REQUIRE(unlink(tmpfile) == 0); + ATF_REQUIRE(close(fd) == 0); +} + ATF_TP_ADD_TCS(tp) { @@ -3072,6 +3166,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop1); ATF_TP_ADD_TC(tp, ptrace__parent_terminate_with_pending_sigstop2); ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard); + ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread); return (atf_no_error()); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705121802.v4CI2vjx057018>