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
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ def test_faulthandler_many_threads():

for i in range(nthreads):
loc = {}
src = f"def thread_func_{i}(evt, barrier):\n barrier.wait()\n evt.wait(5)\n"
src = f"def thread_func_{i}(evt, barrier):\n barrier.wait()\n evt.wait(30)\n"
exec(src, {}, loc)
target = loc[f"thread_func_{i}"]
t = threading.Thread(target=target, args=(evt, barrier), name=f"thread-{i}")
Expand All @@ -655,37 +655,39 @@ def test_faulthandler_many_threads():
t.join(timeout=2)
assert False, f"Barrier wait failed: {e!r}"

header_re = re.compile(r'^Thread.+', re.MULTILINE)
func_name_re = re.compile(r'in (thread_func_(\d+))\b')

def find_interleaved_block(out):
headers = list(header_re.finditer(out))
for idx, m in enumerate(headers):
start = m.end()
end = headers[idx + 1].start() if idx + 1 < len(headers) else len(out)
ids = set(m.group(2) for m in func_name_re.finditer(out[start:end]))
if len(ids) > 1:
return m.group(), ids
return None

try:
f = tempfile.TemporaryFile()
faulthandler.dump_traceback(file=f, all_threads=True)
f.flush()
f.seek(0)
out = f.read().decode('utf-8', 'replace')
interleaved_block = None
for _ in range(3):
with tempfile.TemporaryFile() as f:
faulthandler.dump_traceback(file=f, all_threads=True)
f.flush()
f.seek(0)
out = f.read().decode('utf-8', 'replace')
interleaved_block = find_interleaved_block(out)
if interleaved_block is None:
break
assert interleaved_block is None, (
f"Interleaved output detected in block {interleaved_block[0]!r} "
f"with multiple thread func ids: {interleaved_block[1]}"
)
finally:
try:
f.close()
except Exception:
pass
evt.set()
for t in threads:
t.join(timeout=3)

header_re = re.compile(r'Thread.+')
headers = list(header_re.finditer(out))
blocks = []
for idx, m in enumerate(headers):
start = m.end()
end = headers[idx + 1].start() if idx + 1 < len(headers) else len(out)
blocks.append((m.group(), out[start:end]))

func_name_re = re.compile(r'in (thread_func_(\d+))\b')
ids_per_block = []
for header, content in blocks:
ids = set(m.group(2) for m in func_name_re.finditer(content))
if ids:
ids_per_block.append(ids)
assert len(ids) == 1, f"Interleaved output detected in block {header!r} with multiple thread func ids: {ids}"


def test_faulthandler_sigsegv_builtin():
import faulthandler
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
test.test_cprofile.CProfileTest.test_output_file_when_changing_directory @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
# transient: inconsistent running time [GR-67706]
!test.test_cprofile.CProfileTest.test_run_profile_as_module
test.test_cprofile.CProfileTest.test_run_profile_as_module @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_cprofile.CProfileTest.test_throw @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
test.test_cprofile.TestCommandLine.test_sort @ darwin-arm64,linux-aarch64,linux-aarch64-github,linux-x86_64,linux-x86_64-github,win32-AMD64,win32-AMD64-github
# GR-71916
Expand Down
4 changes: 4 additions & 0 deletions graalpython/lib-python/3/pstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ def load_stats(self, arg):
elif hasattr(arg, 'create_stats'):
arg.create_stats()
self.stats = arg.stats
# GraalPy change: our sampling-based cProfile can produce an empty
# stats dict for very short profiled code; that is still a valid
# profile object and should print as 0 function calls.
arg.stats = {}
return
if not self.stats:
raise TypeError("Cannot create or construct a %r object from %r"
% (self.__class__, arg))
Expand Down
Loading