From owner-svn-src-head@freebsd.org Fri May 12 18:02:58 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 98CEBD699AF; Fri, 12 May 2017 18:02:58 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 70DA01EA9; Fri, 12 May 2017 18:02:58 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4CI2vLT057019; Fri, 12 May 2017 18:02:57 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4CI2vjx057018; Fri, 12 May 2017 18:02:57 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201705121802.v4CI2vjx057018@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Fri, 12 May 2017 18:02:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318246 - head/tests/sys/kern X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 12 May 2017 18:02:58 -0000 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 #include #include +#include #include #include #include @@ -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()); }