1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
12 #include "mozilla/Assertions.h"
13 #include "mozilla/DebugOnly.h"
15 #include "InterposerHelper.h"
17 using mozilla::DebugOnly
;
24 struct PthreadCreateParams
{
25 void* (*start_routine
)(void*);
29 // Install the alternate signal stack, returns a pointer to the memory area we
30 // mapped to store the stack only if it was installed successfully, otherwise
32 static void* install_sig_alt_stack(size_t size
) {
33 void* alt_stack_mem
= mmap(nullptr, size
, PROT_READ
| PROT_WRITE
,
34 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
37 .ss_sp
= alt_stack_mem
,
42 int rv
= sigaltstack(&alt_stack
, nullptr);
47 rv
= munmap(alt_stack_mem
, size
);
54 // Uninstall the alternate signal handler and unmaps it. Does nothing if
55 // alt_stack_mem is NULL.
56 static void uninstall_sig_alt_stack(void* alt_stack_ptr
) {
57 SigAltStack
* alt_stack
= static_cast<SigAltStack
*>(alt_stack_ptr
);
59 stack_t disable_alt_stack
= {};
60 disable_alt_stack
.ss_flags
= SS_DISABLE
;
61 DebugOnly
<int> rv
= sigaltstack(&disable_alt_stack
, nullptr);
63 rv
= munmap(alt_stack
->mem
, alt_stack
->size
);
68 // This replaces the routine passed to pthread_create() when a thread is
69 // started, it handles the alternate signal stack and calls the thread's
71 void* set_alt_signal_stack_and_start(PthreadCreateParams
* params
) {
72 void* (*start_routine
)(void*) = params
->start_routine
;
73 void* arg
= params
->arg
;
76 void* thread_rv
= nullptr;
77 static const size_t kSigStackSize
= std::max(size_t(16384), size_t(SIGSTKSZ
));
78 void* alt_stack_mem
= install_sig_alt_stack(kSigStackSize
);
79 SigAltStack alt_stack
{alt_stack_mem
, kSigStackSize
};
80 pthread_cleanup_push(uninstall_sig_alt_stack
, &alt_stack
);
81 thread_rv
= start_routine(arg
);
82 pthread_cleanup_pop(1);
88 // This interposer replaces libpthread's pthread_create() so that we can
89 // inject an alternate signal stack in every new thread.
90 MFBT_API
int pthread_create(pthread_t
* thread
, const pthread_attr_t
* attr
,
91 void* (*start_routine
)(void*), void* arg
) {
92 static const auto real_pthread_create
= GET_REAL_SYMBOL(pthread_create
);
94 PthreadCreateParams
* params
=
95 (PthreadCreateParams
*)malloc(sizeof(PthreadCreateParams
));
96 params
->start_routine
= start_routine
;
99 int result
= real_pthread_create(
100 thread
, attr
, (void* (*)(void*))set_alt_signal_stack_and_start
, params
);