Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148799955
D12794.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D12794.diff
View Options
Index: head/sys/kern/sys_process.c
===================================================================
--- head/sys/kern/sys_process.c
+++ head/sys/kern/sys_process.c
@@ -1129,6 +1129,13 @@
}
sendsig:
+ /*
+ * Clear the pending event for the thread that just
+ * reported its event (p_xthread). This may not be
+ * the thread passed to PT_CONTINUE, PT_STEP, etc. if
+ * the debugger is resuming a different thread.
+ */
+ td2 = p->p_xthread;
if (proctree_locked) {
sx_xunlock(&proctree_lock);
proctree_locked = 0;
Index: head/sys/sys/param.h
===================================================================
--- head/sys/sys/param.h
+++ head/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1200051 /* Master, propagated to newvers */
+#define __FreeBSD_version 1200052 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
Index: head/tests/sys/kern/ptrace_test.c
===================================================================
--- head/tests/sys/kern/ptrace_test.c
+++ head/tests/sys/kern/ptrace_test.c
@@ -3463,6 +3463,174 @@
ATF_REQUIRE(errno == ECHILD);
}
+#if defined(__amd64__) || defined(__i386__)
+/*
+ * Only x86 both define breakpoint() and have a PC after breakpoint so
+ * that restarting doesn't retrigger the breakpoint.
+ */
+static void *
+continue_thread(void *arg)
+{
+ breakpoint();
+ return (NULL);
+}
+
+static __dead2 void
+continue_thread_main(void)
+{
+ pthread_t threads[2];
+
+ CHILD_REQUIRE(pthread_create(&threads[0], NULL, continue_thread,
+ NULL) == 0);
+ CHILD_REQUIRE(pthread_create(&threads[1], NULL, continue_thread,
+ NULL) == 0);
+ CHILD_REQUIRE(pthread_join(threads[0], NULL) == 0);
+ CHILD_REQUIRE(pthread_join(threads[1], NULL) == 0);
+ exit(1);
+}
+
+/*
+ * Ensure that PT_CONTINUE clears the status of the thread that
+ * triggered the stop even if a different thread's LWP was passed to
+ * PT_CONTINUE.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__PT_CONTINUE_different_thread);
+ATF_TC_BODY(ptrace__PT_CONTINUE_different_thread, tc)
+{
+ struct ptrace_lwpinfo pl;
+ pid_t fpid, wpid;
+ lwpid_t lwps[2];
+ bool hit_break[2];
+ int i, j, status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ continue_thread_main();
+ }
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
+ sizeof(pl)) != -1);
+
+ ATF_REQUIRE(ptrace(PT_LWP_EVENTS, wpid, NULL, 1) == 0);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* One of the new threads should report it's birth. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
+ (PL_FLAG_BORN | PL_FLAG_SCX));
+ lwps[0] = pl.pl_lwpid;
+
+ /*
+ * Suspend this thread to ensure both threads are alive before
+ * hitting the breakpoint.
+ */
+ ATF_REQUIRE(ptrace(PT_SUSPEND, lwps[0], NULL, 0) != -1);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* Second thread should report it's birth. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_BORN | PL_FLAG_SCX)) ==
+ (PL_FLAG_BORN | PL_FLAG_SCX));
+ ATF_REQUIRE(pl.pl_lwpid != lwps[0]);
+ lwps[1] = pl.pl_lwpid;
+
+ /* Resume both threads waiting for breakpoint events. */
+ hit_break[0] = hit_break[1] = false;
+ ATF_REQUIRE(ptrace(PT_RESUME, lwps[0], NULL, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+
+ /* One thread should report a breakpoint. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl, sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
+ ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
+ pl.pl_siginfo.si_code == TRAP_BRKPT);
+ if (pl.pl_lwpid == lwps[0])
+ i = 0;
+ else
+ i = 1;
+ hit_break[i] = true;
+
+ /*
+ * Resume both threads but pass the other thread's LWPID to
+ * PT_CONTINUE.
+ */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, lwps[i ^ 1], (caddr_t)1, 0) == 0);
+
+ /*
+ * Will now get two thread exit events and one more breakpoint
+ * event.
+ */
+ for (j = 0; j < 3; j++) {
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
+ sizeof(pl)) != -1);
+
+ if (pl.pl_lwpid == lwps[0])
+ i = 0;
+ else
+ i = 1;
+
+ ATF_REQUIRE_MSG(lwps[i] != 0, "event for exited thread");
+ if (pl.pl_flags & PL_FLAG_EXITED) {
+ ATF_REQUIRE_MSG(hit_break[i],
+ "exited thread did not report breakpoint");
+ lwps[i] = 0;
+ } else {
+ ATF_REQUIRE((pl.pl_flags & PL_FLAG_SI) != 0);
+ ATF_REQUIRE(pl.pl_siginfo.si_signo == SIGTRAP &&
+ pl.pl_siginfo.si_code == TRAP_BRKPT);
+ ATF_REQUIRE_MSG(!hit_break[i],
+ "double breakpoint event");
+ hit_break[i] = true;
+ }
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1, 0) == 0);
+ }
+
+ /* Both threads should have exited. */
+ ATF_REQUIRE(lwps[0] == 0);
+ ATF_REQUIRE(lwps[1] == 0);
+
+ /* The last event should be for the child process's exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+#endif
+
ATF_TP_ADD_TCS(tp)
{
@@ -3515,6 +3683,9 @@
ATF_TP_ADD_TC(tp, ptrace__event_mask_sigkill_discard);
ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_with_SBDRY_thread);
ATF_TP_ADD_TC(tp, ptrace__PT_STEP_with_signal);
+#if defined(__amd64__) || defined(__i386__)
+ ATF_TP_ADD_TC(tp, ptrace__PT_CONTINUE_different_thread);
+#endif
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 21, 7:00 AM (7 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30034293
Default Alt Text
D12794.diff (6 KB)
Attached To
Mode
D12794: Discard the correct thread event reported for a ptrace stop.
Attached
Detach File
Event Timeline
Log In to Comment