Bug 1637377 - Avoid dead lock on user-requested ccov dumps r=marco

Gcc and Clang dumps gcda files just before an exec** or fork functions.
With ccov enabled, we can dump using a SIGUSR1 but if we're in the middle of dump (because of exec** or fork)
then a gcda file can stay locked and then another process can try to get a lock on it for ever.
So to avoid such a situation, we remove the SIGUSR1 handler just before the fork an set it back just after.

Differential Revision: https://phabricator.services.mozilla.com/D78051
This commit is contained in:
Calixte Denizet 2020-06-03 15:06:58 +00:00
parent e0bacdb606
commit 2f9403d63b

View file

@ -228,6 +228,17 @@ bool LaunchApp(const std::vector<std::string>& argv,
return false;
}
#ifdef MOZ_CODE_COVERAGE
// Before gcc/clang 10 there is a gcda dump before the fork.
// This dump mustn't be interrupted by a SIGUSR1 else we may
// have a dead lock (see bug 1637377).
// So we just remove the handler and restore it after the fork
// It's up the child process to set it up.
// Once we switch to gcc/clang 10, we could just remove it in the child
// process
void (*ccovSigHandler)(int) = signal(SIGUSR1, SIG_IGN);
#endif
#ifdef OS_LINUX
pid_t pid = options.fork_delegate ? options.fork_delegate->Fork() : fork();
// WARNING: if pid == 0, only async signal safe operations are permitted from
@ -269,6 +280,12 @@ bool LaunchApp(const std::vector<std::string>& argv,
}
// In the parent:
#ifdef MOZ_CODE_COVERAGE
// Restore the handler for SIGUSR1
signal(SIGUSR1, ccovSigHandler);
#endif
gProcessLog.print("==> process %d launched child process %d\n",
GetCurrentProcId(), pid);
if (options.wait) HANDLE_EINTR(waitpid(pid, 0, 0));