OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_MACOS) | 6 #if defined(TARGET_OS_MACOS) |
7 | 7 |
8 #include <errno.h> // NOLINT | 8 #include <errno.h> // NOLINT |
| 9 #include <assert.h> // NOLINT |
| 10 #include <stdbool.h> // NOLINT |
| 11 #include <sys/types.h> // NOLINT |
| 12 #include <unistd.h> // NOLINT |
| 13 #include <sys/sysctl.h> // NOLINT |
9 | 14 |
10 #include "vm/flags.h" | 15 #include "vm/flags.h" |
11 #include "vm/os.h" | 16 #include "vm/os.h" |
12 #include "vm/profiler.h" | 17 #include "vm/profiler.h" |
13 #include "vm/signal_handler.h" | 18 #include "vm/signal_handler.h" |
14 #include "vm/thread_interrupter.h" | 19 #include "vm/thread_interrupter.h" |
15 | 20 |
16 namespace dart { | 21 namespace dart { |
17 | 22 |
18 #ifndef PRODUCT | 23 #ifndef PRODUCT |
19 | 24 |
20 DECLARE_FLAG(bool, thread_interrupter); | 25 DECLARE_FLAG(bool, thread_interrupter); |
21 DECLARE_FLAG(bool, trace_thread_interrupter); | 26 DECLARE_FLAG(bool, trace_thread_interrupter); |
22 | 27 |
| 28 // Returns true if the current process is being debugged (either |
| 29 // running under the debugger or has a debugger attached post facto). |
| 30 // Code from https://developer.apple.com/library/content/qa/qa1361/_index.html |
| 31 bool ThreadInterrupter::IsDebuggerAttached() { |
| 32 struct kinfo_proc info; |
| 33 // Initialize the flags so that, if sysctl fails for some bizarre |
| 34 // reason, we get a predictable result. |
| 35 info.kp_proc.p_flag = 0; |
| 36 // Initialize mib, which tells sysctl the info we want, in this case |
| 37 // we're looking for information about a specific process ID. |
| 38 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; |
| 39 size_t size = sizeof(info); |
| 40 |
| 41 // Call sysctl. |
| 42 size = sizeof(info); |
| 43 int junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); |
| 44 ASSERT(junk == 0); |
| 45 // We're being debugged if the P_TRACED flag is set. |
| 46 return ((info.kp_proc.p_flag & P_TRACED) != 0); |
| 47 } |
| 48 |
23 class ThreadInterrupterMacOS : public AllStatic { | 49 class ThreadInterrupterMacOS : public AllStatic { |
24 public: | 50 public: |
25 static void ThreadInterruptSignalHandler(int signal, | 51 static void ThreadInterruptSignalHandler(int signal, |
26 siginfo_t* info, | 52 siginfo_t* info, |
27 void* context_) { | 53 void* context_) { |
28 if (signal != SIGPROF) { | 54 if (signal != SIGPROF) { |
29 return; | 55 return; |
30 } | 56 } |
31 Thread* thread = Thread::Current(); | 57 Thread* thread = Thread::Current(); |
32 if (thread == NULL) { | 58 if (thread == NULL) { |
33 return; | 59 return; |
34 } | 60 } |
35 // Extract thread state. | 61 // Extract thread state. |
36 ucontext_t* context = reinterpret_cast<ucontext_t*>(context_); | 62 ucontext_t* context = reinterpret_cast<ucontext_t*>(context_); |
37 mcontext_t mcontext = context->uc_mcontext; | 63 mcontext_t mcontext = context->uc_mcontext; |
38 InterruptedThreadState its; | 64 InterruptedThreadState its; |
39 its.pc = SignalHandler::GetProgramCounter(mcontext); | 65 its.pc = SignalHandler::GetProgramCounter(mcontext); |
40 its.fp = SignalHandler::GetFramePointer(mcontext); | 66 its.fp = SignalHandler::GetFramePointer(mcontext); |
41 its.csp = SignalHandler::GetCStackPointer(mcontext); | 67 its.csp = SignalHandler::GetCStackPointer(mcontext); |
42 its.dsp = SignalHandler::GetDartStackPointer(mcontext); | 68 its.dsp = SignalHandler::GetDartStackPointer(mcontext); |
43 its.lr = SignalHandler::GetLinkRegister(mcontext); | 69 its.lr = SignalHandler::GetLinkRegister(mcontext); |
44 Profiler::SampleThread(thread, its); | 70 Profiler::SampleThread(thread, its); |
45 } | 71 } |
46 }; | 72 }; |
47 | 73 |
48 | 74 |
49 void ThreadInterrupter::InterruptThread(OSThread* thread) { | 75 void ThreadInterrupter::InterruptThread(OSThread* thread) { |
50 if (FLAG_trace_thread_interrupter) { | 76 if (FLAG_trace_thread_interrupter) { |
51 OS::Print("ThreadInterrupter interrupting %p\n", thread->id()); | 77 OS::PrintErr("ThreadInterrupter interrupting %p\n", thread->id()); |
52 } | 78 } |
53 int result = pthread_kill(thread->id(), SIGPROF); | 79 int result = pthread_kill(thread->id(), SIGPROF); |
54 ASSERT((result == 0) || (result == ESRCH)); | 80 ASSERT((result == 0) || (result == ESRCH)); |
55 } | 81 } |
56 | 82 |
57 | 83 |
58 void ThreadInterrupter::InstallSignalHandler() { | 84 void ThreadInterrupter::InstallSignalHandler() { |
59 SignalHandler::Install< | 85 SignalHandler::Install< |
60 ThreadInterrupterMacOS::ThreadInterruptSignalHandler>(); | 86 ThreadInterrupterMacOS::ThreadInterruptSignalHandler>(); |
61 } | 87 } |
62 | 88 |
63 | 89 |
64 void ThreadInterrupter::RemoveSignalHandler() { | 90 void ThreadInterrupter::RemoveSignalHandler() { |
65 SignalHandler::Remove(); | 91 SignalHandler::Remove(); |
66 } | 92 } |
67 | 93 |
68 #endif // !PRODUCT | 94 #endif // !PRODUCT |
69 | 95 |
70 } // namespace dart | 96 } // namespace dart |
71 | 97 |
72 #endif // defined(TARGET_OS_MACOS) | 98 #endif // defined(TARGET_OS_MACOS) |
OLD | NEW |