mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 20:00:11 +08:00
Fix step over breakpoint on Windows (which was detected by TestCreateAfterAttach.py).
llvm-svn: 241475
This commit is contained in:
@@ -52,10 +52,6 @@ TargetThreadWindows::RefreshStateAfterStop()
|
||||
void
|
||||
TargetThreadWindows::WillResume(lldb::StateType resume_state)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (WINDOWS_LOG_THREAD));
|
||||
if (log)
|
||||
log->Printf ("TargetThreadWindows::WillResume (tid = %" PRIi64 ") setting thread resume state to %s",
|
||||
GetID(), StateAsCString(resume_state));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -125,7 +121,7 @@ TargetThreadWindows::GetUnwinder()
|
||||
bool
|
||||
TargetThreadWindows::DoResume()
|
||||
{
|
||||
StateType resume_state = GetResumeState();
|
||||
StateType resume_state = GetTemporaryResumeState();
|
||||
StateType current_state = GetState();
|
||||
if (resume_state == current_state)
|
||||
return true;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
LEVEL = ../../../make
|
||||
|
||||
ENABLE_THREADS := YES
|
||||
C_SOURCES := main.c
|
||||
include $(LEVEL)/Makefile.rules
|
||||
LEVEL = ../../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
ENABLE_STD_THREADS := YES
|
||||
include $(LEVEL)/Makefile.rules
|
||||
|
||||
@@ -44,9 +44,9 @@ class CreateAfterAttachTestCase(TestBase):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
# Find the line numbers for our breakpoints.
|
||||
self.break_1 = line_number('main.c', '// Set first breakpoint here')
|
||||
self.break_2 = line_number('main.c', '// Set second breakpoint here')
|
||||
self.break_3 = line_number('main.c', '// Set third breakpoint here')
|
||||
self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
|
||||
self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
|
||||
self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
|
||||
|
||||
def create_after_attach(self, use_fork):
|
||||
"""Test thread creation after process attach."""
|
||||
@@ -70,13 +70,17 @@ class CreateAfterAttachTestCase(TestBase):
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
|
||||
# This should create a breakpoint in the main thread.
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1)
|
||||
|
||||
# This should create a breakpoint in the second child thread.
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_2, num_expected_locations=1)
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1)
|
||||
|
||||
# This should create a breakpoint in the first child thread.
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_3, num_expected_locations=1)
|
||||
lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1)
|
||||
|
||||
# Note: With std::thread, we cannot rely on particular thread numbers. Using
|
||||
# std::thread may cause the program to spin up a thread pool (and it does on
|
||||
# Windows), so the thread numbers are non-deterministic.
|
||||
|
||||
# Run to the first breakpoint
|
||||
self.runCmd("continue")
|
||||
@@ -84,23 +88,21 @@ class CreateAfterAttachTestCase(TestBase):
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'* thread #1',
|
||||
'stop reason = breakpoint',
|
||||
'thread #2'])
|
||||
'* thread #',
|
||||
'main',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# Change a variable to escape the loop
|
||||
self.runCmd("expression main_thread_continue = 1")
|
||||
|
||||
# Run to the second breakpoint
|
||||
self.runCmd("continue")
|
||||
self.runCmd("thread select 3")
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'thread #1',
|
||||
'thread #2',
|
||||
'* thread #3',
|
||||
'* thread #',
|
||||
'thread_2_func',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# Change a variable to escape the loop
|
||||
@@ -108,14 +110,13 @@ class CreateAfterAttachTestCase(TestBase):
|
||||
|
||||
# Run to the third breakpoint
|
||||
self.runCmd("continue")
|
||||
self.runCmd("thread select 2")
|
||||
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
# Thread 3 may or may not have already exited.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs = ['stopped',
|
||||
'thread #1',
|
||||
'* thread #2',
|
||||
'* thread #',
|
||||
'thread_1_func',
|
||||
'stop reason = breakpoint'])
|
||||
|
||||
# Run to completion
|
||||
|
||||
@@ -1,79 +1,78 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
volatile int g_thread_2_continuing = 0;
|
||||
|
||||
void *
|
||||
thread_1_func (void *input)
|
||||
{
|
||||
// Waiting to be released by the debugger.
|
||||
while (!g_thread_2_continuing) // The debugger will change this value
|
||||
{
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
// Return
|
||||
return NULL; // Set third breakpoint here
|
||||
}
|
||||
|
||||
void *
|
||||
thread_2_func (void *input)
|
||||
{
|
||||
// Waiting to be released by the debugger.
|
||||
int child_thread_continue = 0;
|
||||
while (!child_thread_continue) // The debugger will change this value
|
||||
{
|
||||
usleep(1); // Set second breakpoint here
|
||||
}
|
||||
|
||||
// Release thread 1
|
||||
g_thread_2_continuing = 1;
|
||||
|
||||
// Return
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
pthread_t thread_1;
|
||||
pthread_t thread_2;
|
||||
|
||||
#if defined(__linux__)
|
||||
// Immediately enable any ptracer so that we can allow the stub attach
|
||||
// operation to succeed. Some Linux kernels are locked down so that
|
||||
// only an ancestor process can be a ptracer of a process. This disables that
|
||||
// restriction. Without it, attach-related stub tests will fail.
|
||||
#if defined(PR_SET_PTRACER) && defined(PR_SET_PTRACER_ANY)
|
||||
int prctl_result;
|
||||
|
||||
// For now we execute on best effort basis. If this fails for
|
||||
// some reason, so be it.
|
||||
prctl_result = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
|
||||
(void) prctl_result;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Create a new thread
|
||||
pthread_create (&thread_1, NULL, thread_1_func, NULL);
|
||||
|
||||
// Waiting to be attached by the debugger.
|
||||
int main_thread_continue = 0;
|
||||
while (!main_thread_continue) // The debugger will change this value
|
||||
{
|
||||
usleep(1); // Set first breakpoint here
|
||||
}
|
||||
|
||||
// Create another new thread
|
||||
pthread_create (&thread_2, NULL, thread_2_func, NULL);
|
||||
|
||||
// Wait for the threads to finish.
|
||||
pthread_join(thread_1, NULL);
|
||||
pthread_join(thread_2, NULL);
|
||||
|
||||
printf("Exiting now\n");
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
using std::chrono::microseconds;
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
volatile int g_thread_2_continuing = 0;
|
||||
|
||||
void *
|
||||
thread_1_func (void *input)
|
||||
{
|
||||
// Waiting to be released by the debugger.
|
||||
while (!g_thread_2_continuing) // Another thread will change this value
|
||||
{
|
||||
std::this_thread::sleep_for(microseconds(1));
|
||||
}
|
||||
|
||||
// Return
|
||||
return NULL; // Set third breakpoint here
|
||||
}
|
||||
|
||||
void *
|
||||
thread_2_func (void *input)
|
||||
{
|
||||
// Waiting to be released by the debugger.
|
||||
int child_thread_continue = 0;
|
||||
while (!child_thread_continue) // The debugger will change this value
|
||||
{
|
||||
std::this_thread::sleep_for(microseconds(1)); // Set second breakpoint here
|
||||
}
|
||||
|
||||
// Release thread 1
|
||||
g_thread_2_continuing = 1;
|
||||
|
||||
// Return
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
#if defined(__linux__)
|
||||
// Immediately enable any ptracer so that we can allow the stub attach
|
||||
// operation to succeed. Some Linux kernels are locked down so that
|
||||
// only an ancestor process can be a ptracer of a process. This disables that
|
||||
// restriction. Without it, attach-related stub tests will fail.
|
||||
#if defined(PR_SET_PTRACER) && defined(PR_SET_PTRACER_ANY)
|
||||
int prctl_result;
|
||||
|
||||
// For now we execute on best effort basis. If this fails for
|
||||
// some reason, so be it.
|
||||
prctl_result = prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
|
||||
(void) prctl_result;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Create a new thread
|
||||
std::thread thread_1(thread_1_func, nullptr);
|
||||
|
||||
// Waiting to be attached by the debugger.
|
||||
int main_thread_continue = 0;
|
||||
while (!main_thread_continue) // The debugger will change this value
|
||||
{
|
||||
std::this_thread::sleep_for(microseconds(1)); // Set first breakpoint here
|
||||
}
|
||||
|
||||
// Create another new thread
|
||||
std::thread thread_2(thread_2_func, nullptr);
|
||||
|
||||
// Wait for the threads to finish.
|
||||
thread_1.join();
|
||||
thread_2.join();
|
||||
|
||||
printf("Exiting now\n");
|
||||
}
|
||||
Reference in New Issue
Block a user