Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7e477c9

Browse filesBrowse files
committed
bpo-115773: Add tests to exercise the _Py_DebugOffsets structure
Signed-off-by: Pablo Galindo <pablogsal@gmail.com>
1 parent 7b21403 commit 7e477c9
Copy full SHA for 7e477c9

File tree

Expand file treeCollapse file tree

9 files changed

+495
-1
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+495
-1
lines changed

‎Include/internal/pycore_runtime.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_runtime.h
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ typedef struct _Py_DebugOffsets {
123123
struct _tuple_object {
124124
off_t ob_item;
125125
} tuple_object;
126+
127+
// Unicode object offset;
128+
struct _unicode_object {
129+
off_t state;
130+
off_t length;
131+
size_t asciiobject_size;
132+
} unicode_object;
126133
} _Py_DebugOffsets;
127134

128135
/* Full Python runtime state */

‎Include/internal/pycore_runtime_init.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_runtime_init.h
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ extern PyTypeObject _PyExc_MemoryError;
8383
.tuple_object = { \
8484
.ob_item = offsetof(PyTupleObject, ob_item), \
8585
}, \
86+
.unicode_object = { \
87+
.state = offsetof(PyUnicodeObject, _base._base.state), \
88+
.length = offsetof(PyUnicodeObject, _base._base.length), \
89+
.asciiobject_size = sizeof(PyASCIIObject), \
90+
}, \
8691
}, \
8792
.allocators = { \
8893
.standard = _pymem_allocators_standard_INIT(runtime), \

‎Lib/test/test_external_inspection.py

Copy file name to clipboard
+79Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import unittest
2+
import os
3+
import textwrap
4+
import importlib
5+
import sys
6+
from test.support import os_helper, SHORT_TIMEOUT
7+
from test.support.script_helper import make_script
8+
9+
import subprocess
10+
11+
PROCESS_VM_READV_SUPPORTED = False
12+
13+
try:
14+
from _testexternalinspection import PROCESS_VM_READV_SUPPORTED
15+
from _testexternalinspection import get_stack_trace
16+
except ImportError:
17+
unittest.skip("Test only runs when _testexternalinspection is available")
18+
19+
def _make_test_script(script_dir, script_basename, source):
20+
to_return = make_script(script_dir, script_basename, source)
21+
importlib.invalidate_caches()
22+
return to_return
23+
24+
class TestGetStackTrace(unittest.TestCase):
25+
26+
@unittest.skipIf(sys.platform != "linux", "Test only runs on Linux")
27+
@unittest.skipIf(not PROCESS_VM_READV_SUPPORTED, "Test only runs on Linux with process_vm_readv support")
28+
def test_stack_trace(self):
29+
# Spawn a process with some realistic Python code
30+
script = textwrap.dedent("""\
31+
import time, sys, os
32+
def bar():
33+
for x in range(100):
34+
if x == 50:
35+
baz()
36+
def baz():
37+
foo()
38+
39+
def foo():
40+
fifo = sys.argv[1]
41+
with open(sys.argv[1], "w") as fifo:
42+
fifo.write("ready")
43+
time.sleep(100)
44+
45+
bar()
46+
""")
47+
stack_trace = None
48+
with os_helper.temp_dir() as work_dir:
49+
script_dir = os.path.join(work_dir, "script_pkg")
50+
os.mkdir(script_dir)
51+
fifo = f"{work_dir}/the_fifo"
52+
os.mkfifo(fifo)
53+
script_name = _make_test_script(script_dir, 'script', script)
54+
try:
55+
p = subprocess.Popen([sys.executable, script_name, str(fifo)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, text=True)
56+
with open(fifo, "r") as fifo_file:
57+
response = fifo_file.read()
58+
self.assertEqual(response, "ready")
59+
stack_trace = get_stack_trace(p.pid)
60+
except PermissionError:
61+
self.skipTest("Insufficient permissions to read the stack trace")
62+
finally:
63+
os.remove(fifo)
64+
p.kill()
65+
p.terminate()
66+
p.kill()
67+
p.wait(timeout=SHORT_TIMEOUT)
68+
69+
70+
expected_stack_trace = [
71+
'foo',
72+
'baz',
73+
'bar',
74+
'<module>'
75+
]
76+
self.assertEqual(stack_trace, expected_stack_trace)
77+
78+
if __name__ == "__main__":
79+
unittest.main()

‎Modules/Setup

Copy file name to clipboardExpand all lines: Modules/Setup
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ PYTHONPATH=$(COREPYTHONPATH)
285285
#_testcapi _testcapimodule.c
286286
#_testimportmultiple _testimportmultiple.c
287287
#_testmultiphase _testmultiphase.c
288+
#_testexternalinspection _testexternalinspection.c
288289
#_testsinglephase _testsinglephase.c
289290

290291
# ---

‎Modules/Setup.stdlib.in

Copy file name to clipboardExpand all lines: Modules/Setup.stdlib.in
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
@MODULE__TESTIMPORTMULTIPLE_TRUE@_testimportmultiple _testimportmultiple.c
172172
@MODULE__TESTMULTIPHASE_TRUE@_testmultiphase _testmultiphase.c
173173
@MODULE__TESTMULTIPHASE_TRUE@_testsinglephase _testsinglephase.c
174+
@MODULE__TESTEXTERNALINSPECTION_TRUE@_testexternalinspection _testexternalinspection.c
174175
@MODULE__CTYPES_TEST_TRUE@_ctypes_test _ctypes/_ctypes_test.c
175176

176177
# Limited API template modules; must be built as shared modules.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.