-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
gh-133953: Add attach command to pdb
#133954
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
base: main
Are you sure you want to change the base?
Changes from 10 commits
3fef8c7
9ddd100
2a9887f
f48a1c6
93e5f58
5297666
ae9669c
1e774a0
b3ffe8c
13d77ad
9c83026
455d9bb
77fb481
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -709,6 +709,27 @@ def _get_asyncio_task(self): | |||||||||||||||||||||
| task = None | ||||||||||||||||||||||
| return task | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| def _get_pid_from_process(self, process): | ||||||||||||||||||||||
| """process could be a subprocess.Popen, multiprocessing.Process or a pid | ||||||||||||||||||||||
| """ | ||||||||||||||||||||||
| # They are not used elsewhere so do a lazy import | ||||||||||||||||||||||
| from multiprocessing import Process | ||||||||||||||||||||||
| from subprocess import Popen | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| try: | ||||||||||||||||||||||
| process = self._getval(process) | ||||||||||||||||||||||
| except: | ||||||||||||||||||||||
| # Error message is already displayed | ||||||||||||||||||||||
| return None | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if isinstance(process, (Process, Popen)): | ||||||||||||||||||||||
|
||||||||||||||||||||||
| return process.pid | ||||||||||||||||||||||
|
||||||||||||||||||||||
| elif isinstance(process, int): | ||||||||||||||||||||||
| return process | ||||||||||||||||||||||
|
||||||||||||||||||||||
| if isinstance(process, (Process, Popen)): | |
| return process.pid | |
| elif isinstance(process, int): | |
| return process | |
| if isinstance(process, int): | |
| return process | |
| pid = getattr(process, "pid", None) | |
| if isinstance(pid, int): | |
| return pid |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably should use the repr here, instead:
| self.error(f"Invalid process {process}") | |
| self.error(f"Invalid process {process!r}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some assumptions in attach that the _PdbClient is being run from the main thread - the entire signal handling approach relies upon it, at the very least - I think it'll just wind up failing with an exception if run from a non-main thread, at the point where it tries to install the signal handler.
I think we should check if we're in the main thread explicitly and self.error() if not.
Or, thinking outside of the box, we could spawn a new process to do the attaching from its main thread, and return control back to the parent process after it finishes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The great thing about attaching directly from the process is that there's the automatic parent-child relation. So even with the tracing restriction, you can still attach to your child processes - spawning a new process won't let you do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, and that's a nice advantage - but certainly not one big enough to live with Ctrl+C not working! And you only get that advantage when starting off in non-remote PDB - if you started off in remote PDB, the child process won't be a child of the client (which means it also won't work when you attach to a child process and then attach again to a grandchild process).
The most reasonable choice might just be to make it so that the pdb.attach module level function raises an exception if it's called from any thread but the main thread. Then the attach PDB command will work from any thread when running remote PDB, and from the main thread when running normal PDB, but will fail when when called on a non-main thread in non-remote PDB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(which means it also won't work when you attach to a child process and then attach again to a grandchild process).
Is that true? I thought the trace_scope applies to descendants, not only direct children. So grandchildren should work? (I have a test that does that, if our linux buildbot has the restriction, it should prove the theory)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The most reasonable choice might just be to make it so that the pdb.attach module level function raises an exception if it's called from any thread but the main thread.
That seems a reasonable option. It won't work when _PdbClient is not in the main thread. We can explore other options in the future, but for now, making what works work seems to be the way to go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(which means it also won't work when you attach to a child process and then attach again to a grandchild process).
Is that true? I thought the trace_scope applies to descendants, not only direct children. So grandchildren should work?
Ah, yes, you're right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably worth adding a comment explaining what this message type is used for, if only for consistency with the other message types.
| case {"attach": int()}: | |
| case {"attach": int()}: | |
| # Have the client to attach to a new process. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ``attach`` command is added to :mod:`pdb` to attach to a running process. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, this seems misleading -
processis really a string that evaluates to aPopenor aProcessor a pid.