Skip to content

Commit b964123

Browse files
authored
Merge branch 'main' into users/rampitec/08-04-_amdgpu_add_fixed_size_to_wmma_instructions_with_scale
2 parents 887f510 + a708b4b commit b964123

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,54 @@ struct ScopedSetTracerPID {
403403
}
404404
};
405405

406+
// This detects whether ptrace is blocked (e.g., by seccomp), by forking and
407+
// then attempting ptrace.
408+
// This separate check is necessary because StopTheWorld() creates a child
409+
// process with a shared virtual address space and shared TLS, and therefore
410+
// cannot use waitpid() due to the shared errno.
411+
static void TestPTrace() {
412+
// Heuristic: only check the first time this is called. This is not always
413+
// correct (e.g., user manually triggers leak detection, then updates
414+
// seccomp, then leak detection is triggered again).
415+
static bool checked = false;
416+
if (checked)
417+
return;
418+
checked = true;
419+
420+
// We hope that fork() is not too expensive, because of copy-on-write.
421+
// Besides, this is only called the first time.
422+
int pid = internal_fork();
423+
424+
if (pid < 0) {
425+
int rverrno;
426+
if (internal_iserror(pid, &rverrno)) {
427+
Report("WARNING: TestPTrace() failed to fork (errno %d)\n", rverrno);
428+
}
429+
_exit(-1);
430+
}
431+
432+
if (pid == 0) {
433+
// Child subprocess
434+
internal_ptrace(PTRACE_ATTACH, 0, nullptr, nullptr);
435+
_exit(0);
436+
} else {
437+
int wstatus;
438+
internal_waitpid(pid, &wstatus, 0);
439+
440+
if (WIFSIGNALED(wstatus)) {
441+
VReport(0,
442+
"Warning: ptrace appears to be blocked (is seccomp enabled?). "
443+
"LeakSanitizer may hang.\n");
444+
VReport(0, "Child exited with signal %d.\n", WTERMSIG(wstatus));
445+
// We don't abort the sanitizer - it's still worth letting the sanitizer
446+
// try.
447+
}
448+
}
449+
}
450+
406451
void StopTheWorld(StopTheWorldCallback callback, void *argument) {
452+
TestPTrace();
453+
407454
StopTheWorldScope in_stoptheworld;
408455
// Prepare the arguments for TracerThread.
409456
struct TracerThreadArgument tracer_thread_argument;
@@ -457,7 +504,8 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
457504
internal_prctl(PR_SET_PTRACER, tracer_pid, 0, 0, 0);
458505
// Allow the tracer thread to start.
459506
tracer_thread_argument.mutex.Unlock();
460-
// NOTE: errno is shared between this thread and the tracer thread.
507+
// NOTE: errno is shared between this thread and the tracer thread
508+
// (clone was called without CLONE_SETTLS / newtls).
461509
// internal_waitpid() may call syscall() which can access/spoil errno,
462510
// so we can't call it now. Instead we for the tracer thread to finish using
463511
// the spin loop below. Man page for sched_yield() says "In the Linux

0 commit comments

Comments
 (0)