Skip to content

Commit e2ba1b7

Browse files
authored
Merge branch 'main' into gh-138514-fix-getpass-echo-char
2 parents 3629a53 + 32e1e06 commit e2ba1b7

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

Lib/profiling/sampling/__main__.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,66 @@
11
"""Run the sampling profiler from the command line."""
22

3+
import sys
4+
5+
MACOS_PERMISSION_ERROR = """\
6+
🔒 Permission Error: Unable to access process memory on macOS
7+
8+
Tachyon needs elevated permissions to profile processes. Try one of these solutions:
9+
10+
1. Try running again with elevated permissions by running 'sudo -E !!'.
11+
12+
2. If targeting system Python processes:
13+
Note: Apple's System Integrity Protection (SIP) may block access to system
14+
Python binaries. Consider using a user-installed Python instead.
15+
"""
16+
17+
LINUX_PERMISSION_ERROR = """
18+
🔒 Tachyon was unable to acess process memory. This could be because tachyon
19+
has insufficient privileges (the required capability is CAP_SYS_PTRACE).
20+
Unprivileged processes cannot trace processes that they cannot send signals
21+
to or those running set-user-ID/set-group-ID programs, for security reasons.
22+
23+
If your uid matches the uid of the target process you want to analyze, you
24+
can do one of the following to get 'ptrace' scope permissions:
25+
26+
* If you are running inside a Docker container, you need to make sure you
27+
start the container using the '--cap-add=SYS_PTRACE' or '--privileged'
28+
command line arguments. Notice that this may not be enough if you are not
29+
running as 'root' inside the Docker container as you may need to disable
30+
hardening (see next points).
31+
32+
* Try running again with elevated permissions by running 'sudo -E !!'.
33+
34+
* You can disable kernel hardening for the current session temporarily (until
35+
a reboot happens) by running 'echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope'.
36+
"""
37+
38+
WINDOWS_PERMISSION_ERROR = """
39+
🔒 Tachyon requires administrator rights to access process memory on Windows.
40+
Please run your command prompt as Administrator and try again.
41+
"""
42+
43+
GENERIC_PERMISSION_ERROR = """
44+
🔒 Tachyon was unable to access the target process due to operating
45+
system restrictions or missing privileges.
46+
"""
47+
348
from .sample import main
449

50+
def handle_permission_error():
51+
"""Handle PermissionError by displaying appropriate error message."""
52+
if sys.platform == "darwin":
53+
print(MACOS_PERMISSION_ERROR, file=sys.stderr)
54+
elif sys.platform.startswith("linux"):
55+
print(LINUX_PERMISSION_ERROR, file=sys.stderr)
56+
elif sys.platform.startswith("win"):
57+
print(WINDOWS_PERMISSION_ERROR, file=sys.stderr)
58+
else:
59+
print(GENERIC_PERMISSION_ERROR, file=sys.stderr)
60+
sys.exit(1)
61+
562
if __name__ == '__main__':
6-
main()
63+
try:
64+
main()
65+
except PermissionError:
66+
handle_permission_error()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import unittest
2+
from test.support import import_helper, threading_helper
3+
4+
resource = import_helper.import_module("resource")
5+
6+
7+
NTHREADS = 10
8+
LOOP_PER_THREAD = 1000
9+
10+
11+
@threading_helper.requires_working_threading()
12+
class ResourceTest(unittest.TestCase):
13+
@unittest.skipUnless(hasattr(resource, "getrusage"), "needs getrusage")
14+
@unittest.skipUnless(
15+
hasattr(resource, "RUSAGE_THREAD"), "needs RUSAGE_THREAD"
16+
)
17+
def test_getrusage(self):
18+
ru_utime_lst = []
19+
20+
def dummy_work(ru_utime_lst):
21+
for _ in range(LOOP_PER_THREAD):
22+
pass
23+
24+
usage_process = resource.getrusage(resource.RUSAGE_SELF)
25+
usage_thread = resource.getrusage(resource.RUSAGE_THREAD)
26+
# Process user time should be greater than thread user time
27+
self.assertGreater(usage_process.ru_utime, usage_thread.ru_utime)
28+
ru_utime_lst.append(usage_thread.ru_utime)
29+
30+
threading_helper.run_concurrently(
31+
worker_func=dummy_work, args=(ru_utime_lst,), nthreads=NTHREADS
32+
)
33+
34+
usage_process = resource.getrusage(resource.RUSAGE_SELF)
35+
self.assertEqual(len(ru_utime_lst), NTHREADS)
36+
# Process user time should be greater than sum of all thread user times
37+
self.assertGreater(usage_process.ru_utime, sum(ru_utime_lst))
38+
39+
40+
if __name__ == "__main__":
41+
unittest.main()

0 commit comments

Comments
 (0)