This revision was automatically updated to reflect the committed changes.
Closed by commit rG8d9400b65b97: [lldb] [Process/NetBSD] Improve threading 
support (authored by mgorny).
Herald added a project: LLDB.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70022/new/

https://reviews.llvm.org/D70022

Files:
  
lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
  
lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
  
lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
  
lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py
  
lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
  
lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py
  lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
  lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
  lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
  lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h

Index: lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -48,11 +48,16 @@
 private:
   // Interface for friend classes
 
+  Status Resume();
+  Status SingleStep();
+  Status Suspend();
+
   void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
   void SetStoppedByBreakpoint();
   void SetStoppedByTrace();
   void SetStoppedByExec();
   void SetStoppedByWatchpoint(uint32_t wp_index);
+  void SetStoppedWithNoReason();
   void SetStopped();
   void SetRunning();
   void SetStepping();
Index: lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -18,6 +18,11 @@
 #include "lldb/Utility/State.h"
 #include "llvm/Support/Errno.h"
 
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+// clang-format on
+
 #include <sstream>
 
 // clang-format off
@@ -36,6 +41,38 @@
 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
 ), m_stop_description() {}
 
+Status NativeThreadNetBSD::Resume() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (!ret.Success())
+    return ret;
+  ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
+                                           nullptr, GetID());
+  if (ret.Success())
+    SetRunning();
+  return ret;
+}
+
+Status NativeThreadNetBSD::SingleStep() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (!ret.Success())
+    return ret;
+  ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
+                                           nullptr, GetID());
+  if (ret.Success())
+    SetStepping();
+  return ret;
+}
+
+Status NativeThreadNetBSD::Suspend() {
+  Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
+                                                  nullptr, GetID());
+  if (ret.Success())
+    SetStopped();
+  return ret;
+}
+
 void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
                                             const siginfo_t *info) {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
@@ -95,6 +132,13 @@
   m_stop_info.details.signal.signo = SIGTRAP;
 }
 
+void NativeThreadNetBSD::SetStoppedWithNoReason() {
+  SetStopped();
+
+  m_stop_info.reason = StopReason::eStopReasonNone;
+  m_stop_info.details.signal.signo = 0;
+}
+
 void NativeThreadNetBSD::SetStopped() {
   const StateType new_state = StateType::eStateStopped;
   m_state = new_state;
Index: lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -100,6 +100,7 @@
   bool HasThreadNoLock(lldb::tid_t thread_id);
 
   NativeThreadNetBSD &AddThread(lldb::tid_t thread_id);
+  void RemoveThread(lldb::tid_t thread_id);
 
   void MonitorCallback(lldb::pid_t pid, int signal);
   void MonitorExited(lldb::pid_t pid, WaitStatus status);
Index: lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
===================================================================
--- lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -9,7 +9,6 @@
 #include "NativeProcessNetBSD.h"
 
 
-
 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
 #include "lldb/Host/HostProcess.h"
 #include "lldb/Host/common/NativeRegisterContext.h"
@@ -99,6 +98,17 @@
       pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
       Info.GetArchitecture(), mainloop));
 
+  // Enable event reporting
+  ptrace_event_t events;
+  status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
+  if (status.Fail())
+    return status.ToError();
+  // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
+  events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+  status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
+  if (status.Fail())
+    return status.ToError();
+
   status = process_up->ReinitializeThreads();
   if (status.Fail())
     return status.ToError();
@@ -211,17 +221,32 @@
     return;
   }
 
+  NativeThreadNetBSD* thread = nullptr;
+  if (info.psi_lwpid > 0) {
+    for (const auto &t : m_threads) {
+      if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
+        thread = static_cast<NativeThreadNetBSD *>(t.get());
+        break;
+      }
+      static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
+    }
+    if (!thread)
+      LLDB_LOG(log,
+               "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
+               info.psi_lwpid);
+  }
+
   switch (info.psi_siginfo.si_code) {
   case TRAP_BRKPT:
-    for (const auto &thread : m_threads) {
-      static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
-      FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
+    if (thread) {
+      thread->SetStoppedByBreakpoint();
+      FixupBreakpointPCAsNeeded(*thread);
     }
     SetState(StateType::eStateStopped, true);
     break;
   case TRAP_TRACE:
-    for (const auto &thread : m_threads)
-      static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
+    if (thread)
+      thread->SetStoppedByTrace();
     SetState(StateType::eStateStopped, true);
     break;
   case TRAP_EXEC: {
@@ -238,54 +263,54 @@
       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
     SetState(StateType::eStateStopped, true);
   } break;
-  case TRAP_DBREG: {
-    // Find the thread.
-    NativeThreadNetBSD* thread = nullptr;
-    for (const auto &t : m_threads) {
-      if (t->GetID() == info.psi_lwpid) {
-        thread = static_cast<NativeThreadNetBSD *>(t.get());
+  case TRAP_LWP: {
+    ptrace_state_t pst;
+    Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+    if (error.Fail()) {
+      SetState(StateType::eStateInvalid);
+      return;
+    }
+
+    switch (pst.pe_report_event) {
+      case PTRACE_LWP_CREATE:
+        LLDB_LOG(log,
+                 "monitoring new thread, pid = {0}, LWP = {1}", pid,
+                 pst.pe_lwp);
+        AddThread(pst.pe_lwp);
+        break;
+      case PTRACE_LWP_EXIT:
+        LLDB_LOG(log,
+                 "removing exited thread, pid = {0}, LWP = {1}", pid,
+                 pst.pe_lwp);
+        RemoveThread(pst.pe_lwp);
         break;
-      }
     }
-    if (!thread) {
-      LLDB_LOG(log,
-               "thread not found in m_threads, pid = {0}, LWP = {1}",
-               GetID(), info.psi_lwpid);
-      break;
+
+    error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
+    if (error.Fail()) {
+      SetState(StateType::eStateInvalid);
+      return;
     }
+  } break;
+  case TRAP_DBREG: {
+    if (!thread)
+      break;
 
-    // If a watchpoint was hit, report it
     uint32_t wp_index = LLDB_INVALID_INDEX32;
     Status error = thread->GetRegisterContext().GetWatchpointHitIndex(
         wp_index, (uintptr_t)info.psi_siginfo.si_addr);
     if (error.Fail())
       LLDB_LOG(log,
                "received error while checking for watchpoint hits, pid = "
-               "{0}, LWP = {1}, error = {2}",
-               GetID(), info.psi_lwpid, error);
+               "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
     if (wp_index != LLDB_INVALID_INDEX32) {
-      for (const auto &thread : m_threads)
-        static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
-            wp_index);
+      thread->SetStoppedByWatchpoint(wp_index);
       SetState(StateType::eStateStopped, true);
       break;
     }
 
-    // If a breakpoint was hit, report it
-    uint32_t bp_index = LLDB_INVALID_INDEX32;
-    error = thread->GetRegisterContext().GetHardwareBreakHitIndex(
-        bp_index, (uintptr_t)info.psi_siginfo.si_addr);
-    if (error.Fail())
-      LLDB_LOG(log,
-               "received error while checking for hardware "
-               "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
-               GetID(), info.psi_lwpid, error);
-    if (bp_index != LLDB_INVALID_INDEX32) {
-      for (const auto &thread : m_threads)
-        static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
-      SetState(StateType::eStateStopped, true);
-      break;
-    }
+    thread->SetStoppedByTrace();
+    SetState(StateType::eStateStopped, true);
   } break;
   }
 }
@@ -295,9 +320,14 @@
   const auto siginfo_err =
       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
 
-  for (const auto &thread : m_threads) {
-    static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
-        info.psi_siginfo.si_signo, &info.psi_siginfo);
+  for (const auto &abs_thread : m_threads) {
+    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
+    assert(info.psi_lwpid >= 0);
+    if (info.psi_lwpid == 0 ||
+        static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
+      thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
+    else
+      thread.SetStoppedWithNoReason();
   }
   SetState(StateType::eStateStopped, true);
 }
@@ -325,59 +355,133 @@
   return error;
 }
 
+static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
+    const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
+    const ResumeActionList &resume_actions) {
+  // We need to account for three possible scenarios:
+  // 1. no signal being sent.
+  // 2. a signal being sent to one thread.
+  // 3. a signal being sent to the whole process.
+
+  // Count signaled threads.  While at it, determine which signal is being sent
+  // and ensure there's only one.
+  size_t signaled_threads = 0;
+  int signal = LLDB_INVALID_SIGNAL_NUMBER;
+  lldb::tid_t signaled_lwp;
+  for (const auto &thread : threads) {
+    assert(thread && "thread list should not contain NULL threads");
+    const ResumeAction *action =
+        resume_actions.GetActionForThread(thread->GetID(), true);
+    if (action) {
+      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
+        signaled_threads++;
+        if (action->signal != signal) {
+          if (signal != LLDB_INVALID_SIGNAL_NUMBER)
+            return Status("NetBSD does not support passing multiple signals "
+                          "simultaneously")
+                .ToError();
+          signal = action->signal;
+          signaled_lwp = thread->GetID();
+        }
+      }
+    }
+  }
+
+  if (signaled_threads == 0) {
+    ptrace_siginfo_t siginfo;
+    siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
+    return siginfo;
+  }
+
+  if (signaled_threads > 1 && signaled_threads < threads.size())
+    return Status("NetBSD does not support passing signal to 1<i<all threads")
+        .ToError();
+
+  ptrace_siginfo_t siginfo;
+  siginfo.psi_siginfo.si_signo = signal;
+  siginfo.psi_siginfo.si_code = SI_USER;
+  siginfo.psi_siginfo.si_pid = getpid();
+  siginfo.psi_siginfo.si_uid = getuid();
+  if (signaled_threads == 1)
+    siginfo.psi_lwpid = signaled_lwp;
+  else // signal for the whole process
+    siginfo.psi_lwpid = 0;
+  return siginfo;
+}
+
 Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
   LLDB_LOG(log, "pid {0}", GetID());
 
-  const auto &thread = m_threads[0];
-  const ResumeAction *const action =
-      resume_actions.GetActionForThread(thread->GetID(), true);
+  Status ret;
 
-  if (action == nullptr) {
-    LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
-             thread->GetID());
-    return Status();
-  }
+  Expected<ptrace_siginfo_t> siginfo =
+      ComputeSignalInfo(m_threads, resume_actions);
+  if (!siginfo)
+    return Status(siginfo.takeError());
 
-  Status error;
-  int signal =
-      action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
-
-  switch (action->state) {
-  case eStateRunning: {
-    // Run the thread, possibly feeding it the signal.
-    error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
-                                               signal);
-    if (!error.Success())
-      return error;
-    for (const auto &thread : m_threads)
-      static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
-    SetState(eStateRunning, true);
-    break;
-  }
-  case eStateStepping:
-    // Run the thread, possibly feeding it the signal.
-    error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
-                                               signal);
-    if (!error.Success())
-      return error;
-    for (const auto &thread : m_threads)
-      static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
-    SetState(eStateStepping, true);
-    break;
+  for (const auto &abs_thread : m_threads) {
+    assert(abs_thread && "thread list should not contain NULL threads");
+    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
 
-  case eStateSuspended:
-  case eStateStopped:
-    llvm_unreachable("Unexpected state");
+    const ResumeAction *action =
+        resume_actions.GetActionForThread(thread.GetID(), true);
+    // we need to explicit issue suspend requests, so it is simpler to map it
+    // into proper action
+    ResumeAction suspend_action{thread.GetID(), eStateSuspended,
+                                LLDB_INVALID_SIGNAL_NUMBER};
 
-  default:
-    return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
-                  "for pid %" PRIu64 ", tid %" PRIu64,
-                  __FUNCTION__, StateAsCString(action->state), GetID(),
-                  thread->GetID());
+    if (action == nullptr) {
+      LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+               thread.GetID());
+      action = &suspend_action;
+    }
+
+    LLDB_LOG(
+        log,
+        "processing resume action state {0} signal {1} for pid {2} tid {3}",
+        action->state, action->signal, GetID(), thread.GetID());
+
+    switch (action->state) {
+    case eStateRunning:
+      ret = thread.Resume();
+      break;
+    case eStateStepping:
+      ret = thread.SingleStep();
+      break;
+    case eStateSuspended:
+    case eStateStopped:
+      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
+        return Status("Passing signal to suspended thread unsupported");
+
+      ret = thread.Suspend();
+      break;
+
+    default:
+      return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
+                    "for pid %" PRIu64 ", tid %" PRIu64,
+                    __FUNCTION__, StateAsCString(action->state), GetID(),
+                    thread.GetID());
+    }
+
+    if (!ret.Success())
+      return ret;
   }
 
-  return Status();
+  int signal = 0;
+  if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
+    ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
+                        sizeof(*siginfo));
+    if (!ret.Success())
+      return ret;
+    signal = siginfo->psi_siginfo.si_signo;
+  }
+
+  ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
+                      signal);
+  if (ret.Success())
+    SetState(eStateRunning, true);
+  return ret;
 }
 
 Status NativeProcessNetBSD::Halt() {
@@ -649,10 +753,10 @@
 }
 
 NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
-
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
 
+  assert(thread_id > 0);
   assert(!HasThreadNoLock(thread_id) &&
          "attempted to add a thread by id that already exists");
 
@@ -664,6 +768,22 @@
   return static_cast<NativeThreadNetBSD &>(*m_threads.back());
 }
 
+void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
+  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+  LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
+
+  assert(thread_id > 0);
+  assert(HasThreadNoLock(thread_id) &&
+         "attempted to remove a thread that does not exist");
+
+  for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
+    if ((*it)->GetID() == thread_id) {
+      m_threads.erase(it);
+      break;
+    }
+  }
+}
+
 Status NativeProcessNetBSD::Attach() {
   // Attach to the requested process.
   // An attach will cause the thread to stop with a SIGSTOP.
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemote_vContThreads.py
@@ -0,0 +1,149 @@
+from __future__ import print_function
+
+import json
+import re
+
+import gdbremote_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestGdbRemote_vContThreads(gdbremote_testcase.GdbRemoteTestCaseBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    def start_threads(self, num):
+        procs = self.prep_debug_monitor_and_inferior(
+            inferior_args=['thread:new'] * num + ['@started'])
+        # start the process and wait for output
+        self.test_sequence.add_log_lines([
+            "read packet: $c#63",
+            {"type": "output_match", "regex": self.maybe_strict_output_regex(
+                r"@started\r\n")},
+        ], True)
+        # then interrupt it
+        self.add_interrupt_packets()
+        self.add_threadinfo_collection_packets()
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+        threads = self.parse_threadinfo_packets(context)
+        self.assertIsNotNone(threads)
+        self.assertEqual(len(threads), num + 1)
+
+        self.reset_test_sequence()
+        return threads
+
+    def signal_one_thread(self):
+        threads = self.start_threads(1)
+        # try sending a signal to one of the two threads
+        self.test_sequence.add_log_lines([
+            "read packet: $vCont;C{0:x}:{1:x};c#00".format(
+                lldbutil.get_signal_number('SIGUSR1'), threads[0]),
+            {"direction": "send", "regex": r"^\$W00#b7$"},
+        ], True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+    @skipUnlessPlatform(["netbsd"])
+    @debugserver_test
+    def test_signal_one_thread_debugserver(self):
+        self.init_debugserver_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_one_thread()
+
+    @skipUnlessPlatform(["netbsd"])
+    @llgs_test
+    def test_signal_one_thread_llgs(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_one_thread()
+
+    def signal_all_threads(self):
+        threads = self.start_threads(1)
+        # try sending a signal to two threads (= the process)
+        self.test_sequence.add_log_lines([
+            "read packet: $vCont;C{0:x}:{1:x};C{0:x}:{2:x}#00".format(
+                lldbutil.get_signal_number('SIGUSR1'),
+                threads[0], threads[1]),
+            {"direction": "send", "regex": r"^\$W00#b7$"},
+        ], True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+    @skipUnlessPlatform(["netbsd"])
+    @debugserver_test
+    def test_signal_all_threads_debugserver(self):
+        self.init_debugserver_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_all_threads()
+
+    @skipUnlessPlatform(["netbsd"])
+    @llgs_test
+    def test_signal_all_threads_llgs(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_all_threads()
+
+    def signal_two_of_three_threads(self):
+        threads = self.start_threads(2)
+        # try sending a signal to 2 out of 3 threads
+        self.test_sequence.add_log_lines([
+            "read packet: $vCont;C{0:x}:{1:x};C{0:x}:{2:x};c#00".format(
+                lldbutil.get_signal_number('SIGUSR1'),
+                threads[1], threads[2]),
+            {"direction": "send", "regex": r"^\$E1e#db$"},
+        ], True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+    @skipUnlessPlatform(["netbsd"])
+    @debugserver_test
+    def test_signal_two_of_three_threads_debugserver(self):
+        self.init_debugserver_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_two_of_three_threads()
+
+    @skipUnlessPlatform(["netbsd"])
+    @llgs_test
+    def test_signal_two_of_three_threads_llgs(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_two_of_three_threads()
+
+    def signal_two_signals(self):
+        threads = self.start_threads(1)
+        # try sending two different signals to two threads
+        self.test_sequence.add_log_lines([
+            "read packet: $vCont;C{0:x}:{1:x};C{2:x}:{3:x}#00".format(
+                lldbutil.get_signal_number('SIGUSR1'), threads[0],
+                lldbutil.get_signal_number('SIGUSR2'), threads[1]),
+            {"direction": "send", "regex": r"^\$E1e#db$"},
+        ], True)
+
+        context = self.expect_gdbremote_sequence()
+        self.assertIsNotNone(context)
+
+    @skipUnlessPlatform(["netbsd"])
+    @debugserver_test
+    def test_signal_two_signals_debugserver(self):
+        self.init_debugserver_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_two_signals()
+
+    @skipUnlessPlatform(["netbsd"])
+    @llgs_test
+    def test_signal_two_signals_llgs(self):
+        self.init_llgs_test()
+        self.build()
+        self.set_inferior_startup_launch()
+        self.signal_two_signals()
Index: lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
+++ lldb/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
@@ -27,7 +27,6 @@
         self.violating_func = "do_bad_thing_with_location"
 
     @add_test_categories(['pyapi'])
-    @expectedFailureNetBSD
     def test_watch_address(self):
         """Exercise SBTarget.WatchAddress() API to set a watchpoint."""
         self.build()
Index: lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py
+++ lldb/packages/Python/lldbsuite/test/python_api/lldbutil/iter/TestLLDBIterator.py
@@ -91,7 +91,6 @@
             self.assertTrue(yours[i] == mine[i],
                             "ID of yours[{0}] and mine[{0}] matches".format(i))
 
-    @expectedFailureNetBSD
     @add_test_categories(['pyapi'])
     def test_lldb_iter_frame(self):
         """Test iterator works correctly for SBProcess->SBThread->SBFrame."""
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
@@ -25,13 +25,11 @@
     @add_test_categories(['pyapi'])
 
     @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working
-    @expectedFailureNetBSD
     def test_thread_id(self):
         self.do_test(set_thread_id)
 
     @skipUnlessDarwin
     @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k'], bugnumber='rdar://problem/34563920') # armv7 ios problem - breakpoint with tid qualifier isn't working
-    @expectedFailureNetBSD
     def test_thread_name(self):
         self.do_test(set_thread_name)
 
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
@@ -25,7 +25,6 @@
         self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here')
 
     @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
-    @expectedFailureNetBSD
     def test(self):
         """Test thread exit handling."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
@@ -23,7 +23,6 @@
         self.thread3_notify_all_line = line_number('main.cpp', '// Set thread3 break point on notify_all at this line.')
         self.thread3_before_lock_line = line_number('main.cpp', '// thread3-before-lock')
 
-    @expectedFailureNetBSD
     def test_number_of_threads(self):
         """Test number of threads."""
         self.build()
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
@@ -17,7 +17,6 @@
 
     @skipIfFreeBSD  # llvm.org/pr21411: test is hanging
     @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
-    @expectedFailureNetBSD
     def test(self):
         """Test thread exit during step handling."""
         self.build(dictionary=self.getBuildFlags())
@@ -28,7 +27,6 @@
 
     @skipIfFreeBSD  # llvm.org/pr21411: test is hanging
     @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
-    @expectedFailureNetBSD
     def test_step_over(self):
         """Test thread exit during step-over handling."""
         self.build(dictionary=self.getBuildFlags())
@@ -39,7 +37,6 @@
 
     @skipIfFreeBSD  # llvm.org/pr21411: test is hanging
     @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
-    @expectedFailureNetBSD
     def test_step_in(self):
         """Test thread exit during step-in handling."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
@@ -21,7 +21,6 @@
         # Find the line number for our breakpoint.
         self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
 
-    @expectedFailureNetBSD
     def test(self):
         """Test thread exit during breakpoint handling."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentTwoBreakpointThreads.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """Test two threads that trigger a breakpoint. """
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """Test signal and a breakpoint in multiple threads."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyCrash.py
@@ -14,7 +14,6 @@
 
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     @skipIfOutOfTreeDebugserver
     def test(self):
         """Test 100 threads that cause a segfault."""
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py
@@ -14,7 +14,6 @@
 
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     @skipIfOutOfTreeDebugserver
     def test(self):
         """Test 100 breakpoints from 100 threads."""
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     @add_test_categories(["watchpoint"])
     def test(self):
         """ Test a thread with a delayed crash while other threads hit a watchpoint and a breakpoint. """
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """ Test a thread with a delayed crash while other threads generate a signal and hit a breakpoint. """
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentDelaySignalBreak.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """Test (1-second delay) signal and a breakpoint in multiple threads."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpointBreakpointSignal.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     @add_test_categories(["watchpoint"])
     def test(self):
         """ Test a thread that crashes while other threads generate a signal and hit a watchpoint and breakpoint. """
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithWatchpoint.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     @add_test_categories(["watchpoint"])
     def test(self):
         """ Test a thread that crashes while another thread hits a watchpoint."""
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithSignal.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """ Test a thread that crashes while another thread generates a signal."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentCrashWithBreak.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """ Test a thread that crashes while another thread hits a breakpoint."""
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/thread/concurrent_events/TestConcurrentBreakpointOneDelayBreakpointThreads.py
@@ -15,7 +15,6 @@
     @skipIfFreeBSD  # timing out on buildbot
     # Atomic sequences are not supported yet for MIPS in LLDB.
     @skipIf(triple='^mips')
-    @expectedFailureNetBSD
     def test(self):
         """Test threads that trigger a breakpoint where one thread has a 1 second delay. """
         self.build(dictionary=self.getBuildFlags())
Index: lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py
+++ lldb/packages/Python/lldbsuite/test/commands/watchpoints/watchpoint_set_command/TestWatchLocationWithWatchSet.py
@@ -34,7 +34,6 @@
             'aarch64',
             'arm'],
         bugnumber="llvm.org/pr26031")
-    @expectedFailureNetBSD
     def test_watchlocation_using_watchpoint_set(self):
         """Test watching a location with 'watchpoint set expression -w write -s size' option."""
         self.build()
Index: lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
+++ lldb/packages/Python/lldbsuite/test/commands/watchpoints/hello_watchlocation/TestWatchLocation.py
@@ -36,7 +36,6 @@
     @expectedFailureAll(triple=re.compile('^mips'))
     # SystemZ and PowerPC also currently supports only one H/W watchpoint
     @expectedFailureAll(archs=['powerpc64le', 's390x'])
-    @expectedFailureNetBSD
     @skipIfDarwin
     def test_hello_watchlocation(self):
         """Test watching a location with '-s size' option."""
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to