mirror of
https://github.com/rui314/mold.git
synced 2024-10-26 13:10:46 +03:00
78 lines
2.2 KiB
C++
78 lines
2.2 KiB
C++
#include "common.h"
|
|
|
|
#include <signal.h>
|
|
#include <tbb/version.h>
|
|
|
|
namespace mold {
|
|
|
|
std::string errno_string() {
|
|
// strerror is not thread-safe, so guard it with a lock.
|
|
static std::mutex mu;
|
|
std::scoped_lock lock(mu);
|
|
return strerror(errno);
|
|
}
|
|
|
|
// mold mmap's an output file, and the mmap succeeds even if there's
|
|
// no enough space left on the filesystem. The actual disk blocks are
|
|
// not allocated on the mmap call but when the program writes to it
|
|
// for the first time.
|
|
//
|
|
// If a disk becomes full as a result of a write to an mmap'ed memory
|
|
// region, the failure of the write is reported as a SIGBUS or structured
|
|
// exeption with code EXCEPTION_IN_PAGE_ERROR on Windows. This
|
|
// signal handler catches that signal and prints out a user-friendly
|
|
// error message. Without this, it is very hard to realize that the
|
|
// disk might be full.
|
|
static std::string sigabrt_msg;
|
|
|
|
static void sighandler(int signo, siginfo_t *info, void *ucontext) {
|
|
static std::mutex mu;
|
|
std::scoped_lock lock{mu};
|
|
|
|
// Handle disk full error
|
|
switch (signo) {
|
|
case SIGSEGV:
|
|
case SIGBUS:
|
|
if (output_buffer_start <= info->si_addr &&
|
|
info->si_addr < output_buffer_end) {
|
|
const char msg[] = "mold: failed to write to an output file. Disk full?\n";
|
|
(void)!write(STDERR_FILENO, msg, sizeof(msg) - 1);
|
|
}
|
|
break;
|
|
case SIGABRT: {
|
|
(void)!write(STDERR_FILENO, &sigabrt_msg[0], sigabrt_msg.size());
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Re-throw the signal
|
|
signal(SIGSEGV, SIG_DFL);
|
|
signal(SIGBUS, SIG_DFL);
|
|
signal(SIGABRT, SIG_DFL);
|
|
|
|
raise(signo);
|
|
}
|
|
|
|
void install_signal_handler() {
|
|
struct sigaction action;
|
|
action.sa_sigaction = sighandler;
|
|
sigemptyset(&action.sa_mask);
|
|
action.sa_flags = SA_SIGINFO;
|
|
|
|
sigaction(SIGSEGV, &action, NULL);
|
|
sigaction(SIGBUS, &action, NULL);
|
|
|
|
// OneTBB 2021.9.0 has the interface version 12090.
|
|
if (TBB_runtime_interface_version() < 12090) {
|
|
sigabrt_msg = "mold: aborted\n"
|
|
"mold: mold with libtbb version 2021.9.0 or older is known to be unstable "
|
|
"under heavy load. Your libtbb version is " +
|
|
std::string(TBB_runtime_version()) +
|
|
". Please upgrade your libtbb library and try again.\n";
|
|
|
|
sigaction(SIGABRT, &action, NULL);
|
|
}
|
|
}
|
|
|
|
} // namespace mold
|