mirror of
https://github.com/corda/corda.git
synced 2025-01-07 13:38:47 +00:00
fix Mac OS MySystem::visit and MySystem::Thread::interrupt implementations
On Mac OS, signals sent using pthread_kill are never delivered if the target thread is blocked (e.g. acquiring a lock or waiting on a condition), so we can't rely on it and must use the Mach-specific thread execution API instead to implement Thread.getStackTrace. For Thread.interrupt, we must not only use pthread_kill but also pthread_cond_signal to ensure the thread is woken up.
This commit is contained in:
parent
2ce549d3f8
commit
00307b9b30
@ -14,6 +14,7 @@
|
||||
# include "CoreFoundation/CoreFoundation.h"
|
||||
# undef assert
|
||||
# define _XOPEN_SOURCE
|
||||
# define _DARWIN_C_SOURCE
|
||||
#endif
|
||||
|
||||
#include "sys/mman.h"
|
||||
@ -144,6 +145,12 @@ class MySystem: public System {
|
||||
r->setInterrupted(true);
|
||||
|
||||
pthread_kill(thread, InterruptSignal);
|
||||
|
||||
// pthread_kill won't necessarily wake a thread blocked in
|
||||
// pthread_cond_{timed}wait (it does on Linux but not Mac OS),
|
||||
// so we signal the condition as well:
|
||||
int rv UNUSED = pthread_cond_signal(&condition);
|
||||
expect(s, rv == 0);
|
||||
}
|
||||
|
||||
virtual void join() {
|
||||
@ -641,14 +648,41 @@ class MySystem: public System {
|
||||
return registerHandler(handler, DivideByZeroSignalIndex);
|
||||
}
|
||||
|
||||
virtual Status visit(System::Thread* st, System::Thread* sTarget,
|
||||
virtual Status visit(System::Thread* st UNUSED, System::Thread* sTarget,
|
||||
ThreadVisitor* visitor)
|
||||
{
|
||||
assert(this, st != sTarget);
|
||||
|
||||
Thread* t = static_cast<Thread*>(st);
|
||||
Thread* target = static_cast<Thread*>(sTarget);
|
||||
|
||||
#ifdef __APPLE__
|
||||
// On Mac OS, signals sent using pthread_kill are never delivered
|
||||
// if the target thread is blocked (e.g. acquiring a lock or
|
||||
// waiting on a condition), so we can't rely on it and must use
|
||||
// the Mach-specific thread execution API instead.
|
||||
|
||||
mach_port_t port = pthread_mach_thread_np(target->thread);
|
||||
|
||||
if (thread_suspend(port)) return -1;
|
||||
|
||||
THREAD_STATE_TYPE state;
|
||||
mach_msg_type_number_t stateCount = THREAD_STATE_COUNT;
|
||||
kern_return_t rv = thread_get_state
|
||||
(port, THREAD_STATE, reinterpret_cast<thread_state_t>(&state),
|
||||
&stateCount);
|
||||
|
||||
if (rv == 0) {
|
||||
visitor->visit(reinterpret_cast<void*>(THREAD_STATE_IP(state)),
|
||||
reinterpret_cast<void*>(THREAD_STATE_STACK(state)),
|
||||
reinterpret_cast<void*>(THREAD_STATE_LINK(state)));
|
||||
}
|
||||
|
||||
thread_resume(port);
|
||||
|
||||
return rv ? -1 : 0;
|
||||
#else // not __APPLE__
|
||||
Thread* t = static_cast<Thread*>(st);
|
||||
|
||||
ACQUIRE_MONITOR(t, visitLock);
|
||||
|
||||
while (threadVisitor) visitLock->wait(t, 0);
|
||||
@ -674,6 +708,7 @@ class MySystem: public System {
|
||||
system->visitLock->notifyAll(t);
|
||||
|
||||
return result;
|
||||
#endif // not __APPLE__
|
||||
}
|
||||
|
||||
virtual uint64_t call(void* function, uintptr_t* arguments, uint8_t* types,
|
||||
|
@ -14,20 +14,37 @@
|
||||
#include "types.h"
|
||||
#include "common.h"
|
||||
|
||||
#define VA_LIST(x) (&x)
|
||||
#define VA_LIST(x) (&(x))
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include "mach/mach_types.h"
|
||||
# include "mach/ppc/thread_act.h"
|
||||
# include "mach/ppc/thread_status.h"
|
||||
|
||||
# define THREAD_STATE PPC_THREAD_STATE
|
||||
# define THREAD_STATE_TYPE ppc_thread_state_t
|
||||
# define THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT
|
||||
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_PPC_EXCEPTION_STATE)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__srr0)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__r1)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__r13)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__lr)
|
||||
# define FIELD(x) __##x
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->ss.srr0)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->ss.r1)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.r13)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->ss.lr)
|
||||
# define FIELD(x) x
|
||||
# endif
|
||||
|
||||
# define THREAD_STATE_IP(state) ((state).FIELD(srr0))
|
||||
# define THREAD_STATE_STACK(state) ((state).FIELD(r1))
|
||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(r13))
|
||||
# define THREAD_STATE_LINK(state) ((state).FIELD(lr))
|
||||
|
||||
# define IP_REGISTER(context) \
|
||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||
# define STACK_REGISTER(context) \
|
||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||
# define THREAD_REGISTER(context) \
|
||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||
# define LINK_REGISTER(context) \
|
||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||
|
||||
#else
|
||||
# error "non-Apple PowerPC-based platforms not yet supported"
|
||||
#endif
|
||||
|
82
src/x86.h
82
src/x86.h
@ -23,27 +23,47 @@
|
||||
#endif
|
||||
|
||||
#if (defined ARCH_x86_32) || (defined PLATFORM_WINDOWS)
|
||||
# define VA_LIST(x) (&x)
|
||||
# define VA_LIST(x) (&(x))
|
||||
#else
|
||||
# define VA_LIST(x) (x)
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include "mach/mach_types.h"
|
||||
# include "mach/i386/thread_act.h"
|
||||
# include "mach/i386/thread_status.h"
|
||||
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||
# define FIELD(x) __##x
|
||||
# else
|
||||
# define FIELD(x) x
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_x86_32
|
||||
|
||||
# ifdef __APPLE__
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__eip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__esp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__ebx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__ecx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext->__ss.__ebp)
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->ss.eip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->ss.esp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.ebx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->ss.ecx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext->ss.ebp)
|
||||
# endif
|
||||
# define THREAD_STATE x86_THREAD_STATE32
|
||||
# define THREAD_STATE_TYPE x86_thread_state32_t
|
||||
# define THREAD_STATE_COUNT x86_THREAD_STATE32_COUNT
|
||||
|
||||
# define THREAD_STATE_IP(state) ((state).FIELD(eip))
|
||||
# define THREAD_STATE_STACK(state) ((state).FIELD(esp))
|
||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(ebx))
|
||||
# define THREAD_STATE_LINK(state) ((state).FIELD(ecx))
|
||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(ebp))
|
||||
|
||||
# define IP_REGISTER(context) \
|
||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||
# define STACK_REGISTER(context) \
|
||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||
# define THREAD_REGISTER(context) \
|
||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||
# define LINK_REGISTER(context) \
|
||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||
# define FRAME_REGISTER(context) \
|
||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_EIP])
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_ESP])
|
||||
@ -70,19 +90,27 @@ dynamicCall(void* function, uintptr_t* arguments, uint8_t*,
|
||||
#elif defined ARCH_x86_64
|
||||
|
||||
# ifdef __APPLE__
|
||||
# if __DARWIN_UNIX03 && defined(_STRUCT_X86_EXCEPTION_STATE32)
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->__ss.__rip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->__ss.__rsp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->__ss.__rbx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->__ss.__rcx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext->__ss.__rbp)
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext->ss.rip)
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext->ss.rsp)
|
||||
# define THREAD_REGISTER(context) (context->uc_mcontext->ss.rbx)
|
||||
# define LINK_REGISTER(context) (context->uc_mcontext->ss.rcx)
|
||||
# define FRAME_REGISTER(context) (context->uc_mcontext->ss.rbp)
|
||||
# endif
|
||||
# define THREAD_STATE x86_THREAD_STATE64
|
||||
# define THREAD_STATE_TYPE x86_thread_state64_t
|
||||
# define THREAD_STATE_COUNT x86_THREAD_STATE64_COUNT
|
||||
|
||||
# define THREAD_STATE_IP(state) ((state).FIELD(rip))
|
||||
# define THREAD_STATE_STACK(state) ((state).FIELD(rsp))
|
||||
# define THREAD_STATE_THREAD(state) ((state).FIELD(rbx))
|
||||
# define THREAD_STATE_LINK(state) ((state).FIELD(rcx))
|
||||
# define THREAD_STATE_FRAME(state) ((state).FIELD(rbp))
|
||||
|
||||
# define IP_REGISTER(context) \
|
||||
THREAD_STATE_IP(context->uc_mcontext->FIELD(ss))
|
||||
# define STACK_REGISTER(context) \
|
||||
THREAD_STATE_STACK(context->uc_mcontext->FIELD(ss))
|
||||
# define THREAD_REGISTER(context) \
|
||||
THREAD_STATE_THREAD(context->uc_mcontext->FIELD(ss))
|
||||
# define LINK_REGISTER(context) \
|
||||
THREAD_STATE_LINK(context->uc_mcontext->FIELD(ss))
|
||||
# define FRAME_REGISTER(context) \
|
||||
THREAD_STATE_FRAME(context->uc_mcontext->FIELD(ss))
|
||||
|
||||
# else
|
||||
# define IP_REGISTER(context) (context->uc_mcontext.gregs[REG_RIP])
|
||||
# define STACK_REGISTER(context) (context->uc_mcontext.gregs[REG_RSP])
|
||||
|
Loading…
Reference in New Issue
Block a user