Skip to content

Commit 7153392

Browse files
authored
Reapply "[fuzzer][Fuchsia] Prevent deadlock from suspending threads" … (llvm#155271)
…(llvm#155042) This reverts commit 781a4db. Relanded with the fix declaring StartRssThread.
1 parent 9ae059b commit 7153392

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

compiler-rt/lib/fuzzer/FuzzerDriver.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ static int RunInMultipleProcesses(const std::vector<std::string> &Args,
306306
return HasErrors ? 1 : 0;
307307
}
308308

309+
static void StartRssThread(Fuzzer *F, size_t RssLimitMb);
310+
311+
// Fuchsia needs to do some book checking before starting the RssThread,
312+
// so it has its own implementation.
313+
#if !LIBFUZZER_FUCHSIA
309314
static void RssThread(Fuzzer *F, size_t RssLimitMb) {
310315
while (true) {
311316
SleepSeconds(1);
@@ -321,6 +326,7 @@ static void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
321326
std::thread T(RssThread, F, RssLimitMb);
322327
T.detach();
323328
}
329+
#endif
324330

325331
int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
326332
Unit U = FileToVector(InputFilePath);

compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ void ExitOnErr(zx_status_t Status, const char *Syscall) {
6868
}
6969

7070
void AlarmHandler(int Seconds) {
71+
// Signal the alarm thread started.
72+
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
73+
"_zx_object_signal alarm");
7174
while (true) {
7275
SleepSeconds(Seconds);
7376
Fuzzer::StaticAlarmCallback();
@@ -282,6 +285,7 @@ void CrashHandler() {
282285
Self, ZX_EXCEPTION_CHANNEL_DEBUGGER, &Channel.Handle),
283286
"_zx_task_create_exception_channel");
284287

288+
// Signal the crash thread started.
285289
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
286290
"_zx_object_signal");
287291

@@ -385,10 +389,49 @@ void StopSignalHandler() {
385389
_zx_handle_close(SignalHandlerEvent);
386390
}
387391

392+
void RssThread(Fuzzer *F, size_t RssLimitMb) {
393+
// Signal the rss thread started.
394+
//
395+
// We must wait for this thread to start because we could accidentally suspend
396+
// it while the crash handler is attempting to handle the
397+
// ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by the
398+
// lsan machinery, then there's no way for this thread to indicate it's
399+
// suspended because it's blocked on waiting for the exception to be handled.
400+
ExitOnErr(_zx_object_signal(SignalHandlerEvent, 0, ZX_USER_SIGNAL_0),
401+
"_zx_object_signal rss");
402+
while (true) {
403+
SleepSeconds(1);
404+
size_t Peak = GetPeakRSSMb();
405+
if (Peak > RssLimitMb)
406+
F->RssLimitCallback();
407+
}
408+
}
409+
388410
} // namespace
389411

412+
void StartRssThread(Fuzzer *F, size_t RssLimitMb) {
413+
// Set up the crash handler and wait until it is ready before proceeding.
414+
assert(SignalHandlerEvent == ZX_HANDLE_INVALID);
415+
ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create");
416+
417+
if (!RssLimitMb)
418+
return;
419+
std::thread T(RssThread, F, RssLimitMb);
420+
T.detach();
421+
422+
// Wait for the rss thread to start.
423+
ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
424+
ZX_TIME_INFINITE, nullptr),
425+
"_zx_object_wait_one rss");
426+
ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0),
427+
"_zx_object_signal rss clear");
428+
}
429+
390430
// Platform specific functions.
391431
void SetSignalHandler(const FuzzingOptions &Options) {
432+
assert(SignalHandlerEvent != ZX_HANDLE_INVALID &&
433+
"This should've been setup by StartRssThread.");
434+
392435
// Make sure information from libFuzzer and the sanitizers are easy to
393436
// reassemble. `__sanitizer_log_write` has the added benefit of ensuring the
394437
// DSO map is always available for the symbolizer.
@@ -404,6 +447,20 @@ void SetSignalHandler(const FuzzingOptions &Options) {
404447
if (Options.HandleAlrm && Options.UnitTimeoutSec > 0) {
405448
std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1);
406449
T.detach();
450+
451+
// Wait for the alarm thread to start.
452+
//
453+
// We must wait for this thread to start because we could accidentally
454+
// suspend it while the crash handler is attempting to handle the
455+
// ZX_EXCP_THREAD_STARTING exception. If the crash handler is suspended by
456+
// the lsan machinery, then there's no way for this thread to indicate it's
457+
// suspended because it's blocked on waiting for the exception to be
458+
// handled.
459+
ExitOnErr(_zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
460+
ZX_TIME_INFINITE, nullptr),
461+
"_zx_object_wait_one alarm");
462+
ExitOnErr(_zx_object_signal(SignalHandlerEvent, ZX_USER_SIGNAL_0, 0),
463+
"_zx_object_signal alarm clear");
407464
}
408465

409466
// Options.HandleInt and Options.HandleTerm are not supported on Fuchsia
@@ -413,9 +470,6 @@ void SetSignalHandler(const FuzzingOptions &Options) {
413470
!Options.HandleFpe && !Options.HandleAbrt && !Options.HandleTrap)
414471
return;
415472

416-
// Set up the crash handler and wait until it is ready before proceeding.
417-
ExitOnErr(_zx_event_create(0, &SignalHandlerEvent), "_zx_event_create");
418-
419473
SignalHandler = std::thread(CrashHandler);
420474
zx_status_t Status = _zx_object_wait_one(SignalHandlerEvent, ZX_USER_SIGNAL_0,
421475
ZX_TIME_INFINITE, nullptr);

0 commit comments

Comments
 (0)