Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
gh-138122: Skip threads on EPERM in blocking mode profiler
When using blocking mode in the remote debugging profiler, ptrace calls
to seize threads can fail with EPERM if the thread has exited between
listing and attaching, is in a special kernel state, or is already being
traced. Previously this raised a RuntimeError that was caught by the
Python sampling loop,and retried indefinitely since EPERM is
a persistent condition that will not resolve on its own.

Treat EPERM the same as ESRCH by returning 1 (skip this thread) instead
of -1 (fatal error). This allows profiling to continue with the threads
that can be traced rather than entering an endless retry loop printing
the same error message repeatedly.
  • Loading branch information
pablogsal committed Jan 2, 2026
commit fc2283b328723a78e0159a028b05218f51344a46
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix endless retry loop in :mod:`profiling.sampling` blocking mode when
threads cannot be seized due to ``EPERM``. Such threads are now skipped
instead of causing repeated error messages. Patch by Pablo Galindo.
10 changes: 8 additions & 2 deletions Modules/_remote_debugging/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,15 +632,21 @@ seize_thread(pid_t tid)
if (errno == ESRCH) {
return 1; // Thread gone, skip
}
if (errno == EPERM) {
// Thread may have exited, be in a special state, or already be traced.
// Skip rather than fail - this avoids endless retry loops when
// threads transiently become inaccessible.
return 1;
}
if (errno == EINVAL || errno == EIO) {
// Fallback for older kernels
if (ptrace(PTRACE_ATTACH, tid, NULL, NULL) == 0) {
int status;
waitpid(tid, &status, __WALL);
return 0;
}
if (errno == ESRCH) {
return 1; // Thread gone
if (errno == ESRCH || errno == EPERM) {
return 1; // Thread gone or inaccessible
}
}
return -1; // Real error
Expand Down
Loading