Skip to content

Fix ASAN failure in TestSingleThreadStepTimeout.py #102208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lldb/include/lldb/Target/ThreadPlanSingleThreadTimeout.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace lldb_private {

class ThreadPlanSingleThreadTimeout;
//
// Thread plan used by single thread execution to issue timeout. This is useful
// to detect potential deadlock in single thread execution. The timeout measures
Expand All @@ -46,6 +47,8 @@ class ThreadPlanSingleThreadTimeout : public ThreadPlan {
bool m_isAlive = false;
ThreadPlanSingleThreadTimeout::State m_last_state = State::WaitTimeout;
};
using TimeoutInfoSP =
std::shared_ptr<ThreadPlanSingleThreadTimeout::TimeoutInfo>;

~ThreadPlanSingleThreadTimeout() override;

Expand All @@ -54,11 +57,11 @@ class ThreadPlanSingleThreadTimeout : public ThreadPlan {
// state. The reference of \param info is passed in so that when
// ThreadPlanSingleThreadTimeout got popped its last state can be stored
// in it for future resume.
static void PushNewWithTimeout(Thread &thread, TimeoutInfo &info);
static void PushNewWithTimeout(Thread &thread, TimeoutInfoSP &info);

// Push a new ThreadPlanSingleThreadTimeout by restoring state from
// input \param info and resume execution.
static void ResumeFromPrevState(Thread &thread, TimeoutInfo &info);
static void ResumeFromPrevState(Thread &thread, TimeoutInfoSP &info);

void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
bool ValidatePlan(Stream *error) override { return true; }
Expand All @@ -78,7 +81,7 @@ class ThreadPlanSingleThreadTimeout : public ThreadPlan {
bool StopOthers() override;

private:
ThreadPlanSingleThreadTimeout(Thread &thread, TimeoutInfo &info);
ThreadPlanSingleThreadTimeout(Thread &thread, TimeoutInfoSP &info);

bool IsTimeoutAsyncInterrupt(Event *event_ptr);
bool HandleEvent(Event *event_ptr);
Expand All @@ -91,7 +94,7 @@ class ThreadPlanSingleThreadTimeout : public ThreadPlan {
const ThreadPlanSingleThreadTimeout &
operator=(const ThreadPlanSingleThreadTimeout &) = delete;

TimeoutInfo &m_info; // Reference to controlling ThreadPlan's TimeoutInfo.
TimeoutInfoSP m_info; // Reference to controlling ThreadPlan's TimeoutInfo.
State m_state;

// Lock for m_wakeup_cv and m_exit_flag between thread plan thread and timer
Expand Down
7 changes: 5 additions & 2 deletions lldb/include/lldb/Target/TimeoutResumeAll.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ namespace lldb_private {
// ResumeWithTimeout() during DoWillResume().
class TimeoutResumeAll {
public:
TimeoutResumeAll(Thread &thread) : m_thread(thread) {}
TimeoutResumeAll(Thread &thread)
: m_thread(thread),
m_timeout_info(
std::make_shared<ThreadPlanSingleThreadTimeout::TimeoutInfo>()) {}

void PushNewTimeout() {
ThreadPlanSingleThreadTimeout::PushNewWithTimeout(m_thread, m_timeout_info);
Expand All @@ -32,7 +35,7 @@ class TimeoutResumeAll {

private:
Thread &m_thread;
ThreadPlanSingleThreadTimeout::TimeoutInfo m_timeout_info;
ThreadPlanSingleThreadTimeout::TimeoutInfoSP m_timeout_info;
};

} // namespace lldb_private
Expand Down
26 changes: 13 additions & 13 deletions lldb/source/Target/ThreadPlanSingleThreadTimeout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@
using namespace lldb_private;
using namespace lldb;

ThreadPlanSingleThreadTimeout::ThreadPlanSingleThreadTimeout(Thread &thread,
TimeoutInfo &info)
ThreadPlanSingleThreadTimeout::ThreadPlanSingleThreadTimeout(
Thread &thread, TimeoutInfoSP &info)
: ThreadPlan(ThreadPlan::eKindSingleThreadTimeout, "Single thread timeout",
thread, eVoteNo, eVoteNoOpinion),
m_info(info), m_state(State::WaitTimeout) {
// TODO: reuse m_timer_thread without recreation.
m_timer_thread = std::thread(TimeoutThreadFunc, this);
m_info.m_isAlive = true;
m_state = m_info.m_last_state;
m_info->m_isAlive = true;
m_state = m_info->m_last_state;
}

ThreadPlanSingleThreadTimeout::~ThreadPlanSingleThreadTimeout() {
m_info.m_isAlive = false;
m_info->m_isAlive = false;
}

uint64_t ThreadPlanSingleThreadTimeout::GetRemainingTimeoutMilliSeconds() {
Expand Down Expand Up @@ -66,7 +66,7 @@ std::string ThreadPlanSingleThreadTimeout::StateToString(State state) {
}

void ThreadPlanSingleThreadTimeout::PushNewWithTimeout(Thread &thread,
TimeoutInfo &info) {
TimeoutInfoSP &info) {
uint64_t timeout_in_ms = thread.GetSingleThreadPlanTimeout();
if (timeout_in_ms == 0)
return;
Expand All @@ -88,13 +88,13 @@ void ThreadPlanSingleThreadTimeout::PushNewWithTimeout(Thread &thread,
}

void ThreadPlanSingleThreadTimeout::ResumeFromPrevState(Thread &thread,
TimeoutInfo &info) {
TimeoutInfoSP &info) {
uint64_t timeout_in_ms = thread.GetSingleThreadPlanTimeout();
if (timeout_in_ms == 0)
return;

// There is already an instance alive.
if (info.m_isAlive)
if (info->m_isAlive)
return;

// Do not create timeout if we are not stopping other threads.
Expand All @@ -118,7 +118,7 @@ bool ThreadPlanSingleThreadTimeout::WillStop() {
LLDB_LOGF(log, "ThreadPlanSingleThreadTimeout::WillStop().");

// Reset the state during stop.
m_info.m_last_state = State::WaitTimeout;
m_info->m_last_state = State::WaitTimeout;
return true;
}

Expand All @@ -128,7 +128,7 @@ void ThreadPlanSingleThreadTimeout::DidPop() {
std::lock_guard<std::mutex> lock(m_mutex);
LLDB_LOGF(log, "ThreadPlanSingleThreadTimeout::DidPop().");
// Tell timer thread to exit.
m_info.m_isAlive = false;
m_info->m_isAlive = false;
}
m_wakeup_cv.notify_one();
// Wait for timer thread to exit.
Expand Down Expand Up @@ -163,12 +163,12 @@ void ThreadPlanSingleThreadTimeout::TimeoutThreadFunc(
" ms",
timeout_in_ms);
self->m_wakeup_cv.wait_for(lock, std::chrono::milliseconds(timeout_in_ms),
[self] { return !self->m_info.m_isAlive; });
[self] { return !self->m_info->m_isAlive; });
LLDB_LOGF(log,
"ThreadPlanSingleThreadTimeout::TimeoutThreadFunc() wake up with "
"m_isAlive(%d).",
self->m_info.m_isAlive);
if (!self->m_info.m_isAlive)
self->m_info->m_isAlive);
if (!self->m_info->m_isAlive)
return;

self->HandleTimeout();
Expand Down
Loading