diff options
author | Ruben Rodriguez <ruben@gnu.org> | 2015-03-08 15:14:03 +0000 |
---|---|---|
committer | Ruben Rodriguez <ruben@gnu.org> | 2015-03-08 15:14:03 +0000 |
commit | 9a0fd32cf6e2ada37675bc743532c5004b16e5e3 (patch) | |
tree | d66faa3279486d2e8ad72bf70e7ef522460372a0 /data/patches/gnuzilla-bug-1036286-1.patch | |
parent | 2732de330618bc29b7ab07f4004d8e84f698cf95 (diff) |
Added patches to fix build bugs for Windows, MacOS and Android
Diffstat (limited to 'data/patches/gnuzilla-bug-1036286-1.patch')
-rw-r--r-- | data/patches/gnuzilla-bug-1036286-1.patch | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/data/patches/gnuzilla-bug-1036286-1.patch b/data/patches/gnuzilla-bug-1036286-1.patch new file mode 100644 index 0000000..a5d3110 --- /dev/null +++ b/data/patches/gnuzilla-bug-1036286-1.patch @@ -0,0 +1,188 @@ +--- a/mozglue/linker/ElfLoader.cpp ++++ a/mozglue/linker/ElfLoader.cpp +@@ -960,28 +960,28 @@ static uint64_t ProcessTimeStamp_Now() + /* Data structure used to pass data to the temporary signal handler, + * as well as triggering a test crash. */ + struct TmpData { + volatile int crash_int; + volatile uint64_t crash_timestamp; + }; + + SEGVHandler::SEGVHandler() +-: registeredHandler(false), signalHandlingBroken(false) +-, signalHandlingSlow(false) ++: initialized(false), registeredHandler(false), signalHandlingBroken(true) ++, signalHandlingSlow(true) + { + /* Initialize oldStack.ss_flags to an invalid value when used to set + * an alternative stack, meaning we haven't got information about the +- * original alternative stack and thus don't mean to restore it */ ++ * original alternative stack and thus don't mean to restore it in ++ * the desctructor. */ + oldStack.ss_flags = SS_ONSTACK; +- if (!Divert(sigaction, __wrap_sigaction)) +- return; + + /* Get the current segfault signal handler. */ +- sys_sigaction(SIGSEGV, nullptr, &this->action); ++ struct sigaction old_action; ++ sys_sigaction(SIGSEGV, nullptr, &old_action); + + /* Some devices don't provide useful information to their SIGSEGV handlers, + * making it impossible for on-demand decompression to work. To check if + * we're on such a device, setup a temporary handler and deliberately + * trigger a segfault. The handler will set signalHandlingBroken if the + * provided information is bogus. + * Some other devices have a kernel option enabled that makes SIGSEGV handler + * have an overhead so high that it affects how on-demand decompression +@@ -1000,21 +1000,33 @@ SEGVHandler::SEGVHandler() + if (sys_sigaction(SIGSEGV, &action, nullptr)) + return; + + TmpData *data = reinterpret_cast<TmpData*>(stackPtr.get()); + data->crash_timestamp = ProcessTimeStamp_Now(); + mprotect(stackPtr, stackPtr.GetLength(), PROT_NONE); + data->crash_int = 123; + /* Restore the original segfault signal handler. */ +- sys_sigaction(SIGSEGV, &this->action, nullptr); ++ sys_sigaction(SIGSEGV, &old_action, nullptr); + stackPtr.Assign(MAP_FAILED, 0); ++} ++ ++void ++SEGVHandler::FinishInitialization() ++{ ++ /* Ideally, we'd need some locking here, but in practice, we're not ++ * going to race with another thread. */ ++ initialized = true; ++ + if (signalHandlingBroken || signalHandlingSlow) + return; + ++ if (!Divert(sigaction, __wrap_sigaction)) ++ return; ++ + /* Setup an alternative stack if the already existing one is not big + * enough, or if there is none. */ + if (sigaltstack(nullptr, &oldStack) == 0) { + if (oldStack.ss_flags == SS_ONSTACK) + oldStack.ss_flags = 0; + if (!oldStack.ss_sp || oldStack.ss_size < stackSize) { + stackPtr.Assign(MemoryRange::mmap(nullptr, stackSize, + PROT_READ | PROT_WRITE, +@@ -1028,17 +1040,17 @@ SEGVHandler::SEGVHandler() + if (sigaltstack(&stack, nullptr) != 0) + return; + } + } + /* Register our own handler, and store the already registered one in + * SEGVHandler's struct sigaction member */ + action.sa_sigaction = &SEGVHandler::handler; + action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK; +- registeredHandler = !sys_sigaction(SIGSEGV, &action, nullptr); ++ registeredHandler = !sys_sigaction(SIGSEGV, &action, &this->action); + } + + SEGVHandler::~SEGVHandler() + { + /* Restore alternative stack for signals */ + if (oldStack.ss_flags != SS_ONSTACK) + sigaltstack(&oldStack, nullptr); + /* Restore original signal handler */ +@@ -1048,28 +1060,28 @@ SEGVHandler::~SEGVHandler() + + /* Test handler for a deliberately triggered SIGSEGV that determines whether + * useful information is provided to signal handlers, particularly whether + * si_addr is filled in properly, and whether the segfault handler is called + * quickly enough. */ + void SEGVHandler::test_handler(int signum, siginfo_t *info, void *context) + { + SEGVHandler &that = ElfLoader::Singleton; +- if (signum != SIGSEGV || +- info == nullptr || info->si_addr != that.stackPtr.get()) +- that.signalHandlingBroken = true; ++ if (signum == SIGSEGV && info && ++ info->si_addr == that.stackPtr.get()) ++ that.signalHandlingBroken = false; + mprotect(that.stackPtr, that.stackPtr.GetLength(), PROT_READ | PROT_WRITE); + TmpData *data = reinterpret_cast<TmpData*>(that.stackPtr.get()); + uint64_t latency = ProcessTimeStamp_Now() - data->crash_timestamp; + DEBUG_LOG("SEGVHandler latency: %" PRIu64, latency); + /* See bug 886736 for timings on different devices, 150 µs is reasonably above +- * the latency on "working" devices and seems to be reasonably fast to incur +- * a huge overhead to on-demand decompression. */ +- if (latency > 150000) +- that.signalHandlingSlow = true; ++ * the latency on "working" devices and seems to be reasonably fast not to ++ * incur a huge overhead to on-demand decompression. */ ++ if (latency <= 150000) ++ that.signalHandlingSlow = false; + } + + /* TODO: "properly" handle signal masks and flags */ + void SEGVHandler::handler(int signum, siginfo_t *info, void *context) + { + //ASSERT(signum == SIGSEGV); + DEBUG_LOG("Caught segmentation fault @%p", info->si_addr); + +--- a/mozglue/linker/ElfLoader.h ++++ a/mozglue/linker/ElfLoader.h +@@ -307,32 +307,40 @@ private: + * faults within the address space of the loaded libraries. It however + * allows a handler to be set for faults in other places, and redispatches + * to the handler set through signal() or sigaction(). + */ + class SEGVHandler + { + public: + bool hasRegisteredHandler() { ++ if (! initialized) ++ FinishInitialization(); + return registeredHandler; + } + + bool isSignalHandlingBroken() { + return signalHandlingBroken; + } + + protected: + SEGVHandler(); + ~SEGVHandler(); + + private: + static int __wrap_sigaction(int signum, const struct sigaction *act, + struct sigaction *oldact); + + /** ++ * The constructor doesn't do all initialization, and the tail is done ++ * at a later time. ++ */ ++ void FinishInitialization(); ++ ++ /** + * SIGSEGV handler registered with __wrap_signal or __wrap_sigaction. + */ + struct sigaction action; + + /** + * ElfLoader SIGSEGV handler. + */ + static void handler(int signum, siginfo_t *info, void *context); +@@ -354,16 +362,17 @@ private: + stack_t oldStack; + + /** + * Pointer to an alternative stack for signals. Only set if oldStack is + * not set or not big enough. + */ + MappedPtr stackPtr; + ++ bool initialized; + bool registeredHandler; + bool signalHandlingBroken; + bool signalHandlingSlow; + }; + + /** + * Elf Loader class in charge of loading and bookkeeping libraries. + */ |