Skip to content

[lldb] [debugserver] Shut down the exception thread when clearing #70979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

jasonmolenda
Copy link
Collaborator

MachProcess has a MachTask as an ivar. In the MachProcess dtor, we call MachTask::Clear() to clear its state, before running the dtor of all our ivars, including the MachTask one.

When we attach on darwin, MachProcess calls MachTask::StartExceptionThread which does the task_for_pid and then starts a thread to listen for mach messages. Then MachProcess calls ptrace(PT_ATTACHEXC). If that ptrace() fails, MachProcess will call MachTask::Clear. But the exception thread is now up & running and is not stopped; its ivars will be reset by the Clear() method, and its object will be freed after the dtor runs.

Actually eliciting a crash in this scenario is very timing sensitive; I hand-modified debugserver to fail to PT_ATTACHEXC trying to simulate it on my desktop and was unable. But looking at the source, and an occasional crash report we've received, it's clear that this is possible.

rdar://117521198

MachProcess has a MachTask as an ivar.  In the MachProcess dtor,
we call MachTask::Clear() to clear its state, before running the
dtor of all our ivars, including the MachTask one.

When we attach on darwin, MachProcess calls MachTask::StartExceptionThread
which does the task_for_pid and then starts a thread to listen for
mach messages.  Then MachProcess calls ptrace(PT_ATTACHEXC).  If
that ptrace() fails, MachProcess will call MachTask::Clear.  But
the exception thread is now up & running and is not stopped; its
ivars will be reset by the Clear() method, and its object will be
freed after the dtor runs.

Actually eliciting a crash in this scenario is very timing sensitive;
I hand-modified debugserver to fail to PT_ATTACHEXC trying to simulate
it on my desktop and was unable.  But looking at the source, and an
occasional crash report we've received, it's clear that this is
possible.

rdar://117521198
@llvmbot
Copy link
Member

llvmbot commented Nov 1, 2023

@llvm/pr-subscribers-lldb

Author: Jason Molenda (jasonmolenda)

Changes

MachProcess has a MachTask as an ivar. In the MachProcess dtor, we call MachTask::Clear() to clear its state, before running the dtor of all our ivars, including the MachTask one.

When we attach on darwin, MachProcess calls MachTask::StartExceptionThread which does the task_for_pid and then starts a thread to listen for mach messages. Then MachProcess calls ptrace(PT_ATTACHEXC). If that ptrace() fails, MachProcess will call MachTask::Clear. But the exception thread is now up & running and is not stopped; its ivars will be reset by the Clear() method, and its object will be freed after the dtor runs.

Actually eliciting a crash in this scenario is very timing sensitive; I hand-modified debugserver to fail to PT_ATTACHEXC trying to simulate it on my desktop and was unable. But looking at the source, and an occasional crash report we've received, it's clear that this is possible.

rdar://117521198


Full diff: https://github.com/llvm/llvm-project/pull/70979.diff

1 Files Affected:

  • (modified) lldb/tools/debugserver/source/MacOSX/MachTask.mm (+2)
diff --git a/lldb/tools/debugserver/source/MacOSX/MachTask.mm b/lldb/tools/debugserver/source/MacOSX/MachTask.mm
index 4f5b4039243f662..fd2ac64ac6cf79c 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachTask.mm
+++ b/lldb/tools/debugserver/source/MacOSX/MachTask.mm
@@ -145,6 +145,8 @@
 //----------------------------------------------------------------------
 void MachTask::Clear() {
   // Do any cleanup needed for this task
+  if (m_exception_thread)
+    ShutDownExcecptionThread();
   m_task = TASK_NULL;
   m_exception_thread = 0;
   m_exception_port = MACH_PORT_NULL;

Copy link
Member

@medismailben medismailben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. LGTM!

@jasonmolenda jasonmolenda merged commit 66b9283 into llvm:main Nov 1, 2023
@jasonmolenda jasonmolenda deleted the stop-exception-thread-in-machtask-clear branch November 1, 2023 23:14
jasonmolenda added a commit to swiftlang/llvm-project that referenced this pull request Nov 2, 2023
…vm#70979)

MachProcess has a MachTask as an ivar. In the MachProcess dtor, we call
MachTask::Clear() to clear its state, before running the dtor of all our
ivars, including the MachTask one.

When we attach on darwin, MachProcess calls
MachTask::StartExceptionThread which does the task_for_pid and then
starts a thread to listen for mach messages. Then MachProcess calls
ptrace(PT_ATTACHEXC). If that ptrace() fails, MachProcess will call
MachTask::Clear. But the exception thread is now up & running and is not
stopped; its ivars will be reset by the Clear() method, and its object
will be freed after the dtor runs.

Actually eliciting a crash in this scenario is very timing sensitive; I
hand-modified debugserver to fail to PT_ATTACHEXC trying to simulate it
on my desktop and was unable. But looking at the source, and an
occasional crash report we've received, it's clear that this is
possible.

rdar://117521198
(cherry picked from commit 66b9283)
jasonmolenda added a commit to swiftlang/llvm-project that referenced this pull request Nov 2, 2023
…tion-thread-from-MachTask-Clear

[lldb] [debugserver] Shut down the exception thread when clearing (llvm#70979)
jasonmolenda added a commit to jasonmolenda/llvm-project that referenced this pull request Nov 8, 2023
…vm#70979)

MachProcess has a MachTask as an ivar. In the MachProcess dtor, we call
MachTask::Clear() to clear its state, before running the dtor of all our
ivars, including the MachTask one.

When we attach on darwin, MachProcess calls
MachTask::StartExceptionThread which does the task_for_pid and then
starts a thread to listen for mach messages. Then MachProcess calls
ptrace(PT_ATTACHEXC). If that ptrace() fails, MachProcess will call
MachTask::Clear. But the exception thread is now up & running and is not
stopped; its ivars will be reset by the Clear() method, and its object
will be freed after the dtor runs.

Actually eliciting a crash in this scenario is very timing sensitive; I
hand-modified debugserver to fail to PT_ATTACHEXC trying to simulate it
on my desktop and was unable. But looking at the source, and an
occasional crash report we've received, it's clear that this is
possible.

rdar://117521198
(cherry picked from commit 66b9283)
jasonmolenda added a commit to swiftlang/llvm-project that referenced this pull request Nov 8, 2023
…-when-clearing

[lldb] [debugserver] Shut down the exception thread when clearing (llvm#70979)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants