Disable the profiler when a debugger is attached

Fixes #28702

BUG=
R=vegorov@google.com

Review-Url: https://codereview.chromium.org/2682343002 .
This commit is contained in:
John McCutchan 2017-02-09 10:11:52 -08:00
parent a4c42824ed
commit 95a8166523
7 changed files with 75 additions and 19 deletions

View file

@ -70,8 +70,17 @@ void ThreadInterrupter::InitOnce() {
void ThreadInterrupter::Startup() {
ASSERT(initialized_);
if (IsDebuggerAttached()) {
MonitorLocker shutdown_ml(monitor_);
shutdown_ = true;
if (FLAG_trace_thread_interrupter) {
OS::PrintErr(
"ThreadInterrupter disabled because a debugger is attached.\n");
}
return;
}
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter starting up.\n");
OS::PrintErr("ThreadInterrupter starting up.\n");
}
ASSERT(interrupter_thread_id_ == OSThread::kInvalidThreadJoinId);
{
@ -83,7 +92,7 @@ void ThreadInterrupter::Startup() {
}
ASSERT(interrupter_thread_id_ != OSThread::kInvalidThreadJoinId);
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter running.\n");
OS::PrintErr("ThreadInterrupter running.\n");
}
}
@ -100,7 +109,7 @@ void ThreadInterrupter::Shutdown() {
shutdown_ml.Notify();
ASSERT(initialized_);
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter shutting down.\n");
OS::PrintErr("ThreadInterrupter shutting down.\n");
}
}
@ -110,7 +119,7 @@ void ThreadInterrupter::Shutdown() {
interrupter_thread_id_ = OSThread::kInvalidThreadJoinId;
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter shut down.\n");
OS::PrintErr("ThreadInterrupter shut down.\n");
}
}
@ -149,7 +158,7 @@ void ThreadInterrupter::ThreadMain(uword parameters) {
ASSERT(initialized_);
InstallSignalHandler();
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter thread running.\n");
OS::PrintErr("ThreadInterrupter thread running.\n");
}
{
// Signal to main thread we are ready.
@ -215,7 +224,7 @@ void ThreadInterrupter::ThreadMain(uword parameters) {
}
RemoveSignalHandler();
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter thread exiting.\n");
OS::PrintErr("ThreadInterrupter thread exiting.\n");
}
{
// Signal to main thread we are exiting.

View file

@ -48,6 +48,8 @@ class ThreadInterrupter : public AllStatic {
static intptr_t interrupt_period_;
static intptr_t current_wait_time_;
static bool IsDebuggerAttached();
static bool InDeepSleep() {
return current_wait_time_ == Monitor::kNoTimeout;
}

View file

@ -47,10 +47,15 @@ class ThreadInterrupterAndroid : public AllStatic {
};
bool ThreadInterrupter::IsDebuggerAttached() {
return false;
}
void ThreadInterrupter::InterruptThread(OSThread* thread) {
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter interrupting %p\n",
reinterpret_cast<void*>(thread->id()));
OS::PrintErr("ThreadInterrupter interrupting %p\n",
reinterpret_cast<void*>(thread->id()));
}
int result = syscall(__NR_tgkill, getpid(), thread->id(), SIGPROF);
ASSERT((result == 0) || (result == ESRCH));

View file

@ -11,6 +11,10 @@
namespace dart {
bool ThreadInterrupter::IsDebuggerAttached() {
return false;
}
void ThreadInterrupter::InterruptThread(OSThread* thread) {
UNIMPLEMENTED();
}

View file

@ -44,10 +44,15 @@ class ThreadInterrupterLinux : public AllStatic {
};
bool ThreadInterrupter::IsDebuggerAttached() {
return false;
}
void ThreadInterrupter::InterruptThread(OSThread* thread) {
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter interrupting %p\n",
reinterpret_cast<void*>(thread->id()));
OS::PrintErr("ThreadInterrupter interrupting %p\n",
reinterpret_cast<void*>(thread->id()));
}
int result = pthread_kill(thread->id(), SIGPROF);
ASSERT((result == 0) || (result == ESRCH));

View file

@ -6,6 +6,11 @@
#if defined(TARGET_OS_MACOS)
#include <errno.h> // NOLINT
#include <assert.h> // NOLINT
#include <stdbool.h> // NOLINT
#include <sys/types.h> // NOLINT
#include <unistd.h> // NOLINT
#include <sys/sysctl.h> // NOLINT
#include "vm/flags.h"
#include "vm/os.h"
@ -20,6 +25,27 @@ namespace dart {
DECLARE_FLAG(bool, thread_interrupter);
DECLARE_FLAG(bool, trace_thread_interrupter);
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
// Code from https://developer.apple.com/library/content/qa/qa1361/_index.html
bool ThreadInterrupter::IsDebuggerAttached() {
struct kinfo_proc info;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
size_t size = sizeof(info);
// Call sysctl.
size = sizeof(info);
int junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
ASSERT(junk == 0);
// We're being debugged if the P_TRACED flag is set.
return ((info.kp_proc.p_flag & P_TRACED) != 0);
}
class ThreadInterrupterMacOS : public AllStatic {
public:
static void ThreadInterruptSignalHandler(int signal,
@ -48,7 +74,7 @@ class ThreadInterrupterMacOS : public AllStatic {
void ThreadInterrupter::InterruptThread(OSThread* thread) {
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter interrupting %p\n", thread->id());
OS::PrintErr("ThreadInterrupter interrupting %p\n", thread->id());
}
int result = pthread_kill(thread->id(), SIGPROF);
ASSERT((result == 0) || (result == ESRCH));

View file

@ -63,8 +63,8 @@ class ThreadInterrupterWin : public AllStatic {
DWORD result = SuspendThread(handle);
if (result == kThreadError) {
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter failed to suspend thread %p\n",
reinterpret_cast<void*>(os_thread->id()));
OS::PrintErr("ThreadInterrupter failed to suspend thread %p\n",
reinterpret_cast<void*>(os_thread->id()));
}
CloseHandle(handle);
return;
@ -74,8 +74,8 @@ class ThreadInterrupterWin : public AllStatic {
// Failed to get thread registers.
ResumeThread(handle);
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter failed to get registers for %p\n",
reinterpret_cast<void*>(os_thread->id()));
OS::PrintErr("ThreadInterrupter failed to get registers for %p\n",
reinterpret_cast<void*>(os_thread->id()));
}
CloseHandle(handle);
return;
@ -93,15 +93,20 @@ class ThreadInterrupterWin : public AllStatic {
};
bool ThreadInterrupter::IsDebuggerAttached() {
return false;
}
void ThreadInterrupter::InterruptThread(OSThread* thread) {
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter suspending %p\n",
reinterpret_cast<void*>(thread->id()));
OS::PrintErr("ThreadInterrupter suspending %p\n",
reinterpret_cast<void*>(thread->id()));
}
ThreadInterrupterWin::Interrupt(thread);
if (FLAG_trace_thread_interrupter) {
OS::Print("ThreadInterrupter resuming %p\n",
reinterpret_cast<void*>(thread->id()));
OS::PrintErr("ThreadInterrupter resuming %p\n",
reinterpret_cast<void*>(thread->id()));
}
}