Revert "[lldb] [Process] Watch for fork/vfork notifications" and associated followups

This commit has caused the following tests to be flaky:
TestThreadSpecificBpPlusCondition.py
TestExitDuringExpression.py

The exact cause is not known yet, but since both tests deal with
threads, my guess is it has something to do with the tracking of
creation of new threads (which the commit touches upon).

This reverts the following commits:
d01bff8cbdc98fb8751f7bf10af19b47ae5c445d,
ba62ebc48e8c424ce3a78ba01acda679d536dd47,
e761b6b4c58d4f7ae1073d925d7cb321d68ee93a,
a345419ee03095c8cdfbe1c2728467c4da8fa0a4.

GitOrigin-RevId: 121cff78a8032a73aa4fb820625dc1ecae8e3997
diff --git a/include/lldb/Host/linux/Host.h b/include/lldb/Host/linux/Host.h
deleted file mode 100644
index 409a9fc..0000000
--- a/include/lldb/Host/linux/Host.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- Host.h --------------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_HOST_LINUX_HOST_H
-#define LLDB_HOST_LINUX_HOST_H
-
-#include "lldb/lldb-types.h"
-#include "llvm/ADT/Optional.h"
-
-namespace lldb_private {
-
-// Get PID (i.e. the primary thread ID) corresponding to the specified TID.
-llvm::Optional<lldb::pid_t> getPIDForTID(lldb::pid_t tid);
-
-} // namespace lldb_private
-
-#endif // #ifndef LLDB_HOST_LINUX_HOST_H
diff --git a/source/Host/linux/Host.cpp b/source/Host/linux/Host.cpp
index 334634a..520a00d 100644
--- a/source/Host/linux/Host.cpp
+++ b/source/Host/linux/Host.cpp
@@ -27,7 +27,6 @@
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/Host.h"
 #include "lldb/Host/HostInfo.h"
-#include "lldb/Host/linux/Host.h"
 #include "lldb/Host/linux/Support.h"
 #include "lldb/Utility/DataExtractor.h"
 
@@ -54,8 +53,7 @@
 }
 
 static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
-                          ProcessState &State, ::pid_t &TracerPid,
-                          ::pid_t &Tgid) {
+                          ProcessState &State, ::pid_t &TracerPid) {
   Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
 
   auto BufferOrError = getProcFile(Pid, "status");
@@ -109,9 +107,6 @@
     } else if (Line.consume_front("TracerPid:")) {
       Line = Line.ltrim();
       Line.consumeInteger(10, TracerPid);
-    } else if (Line.consume_front("Tgid:")) {
-      Line = Line.ltrim();
-      Line.consumeInteger(10, Tgid);
     }
   }
   return true;
@@ -209,7 +204,6 @@
 static bool GetProcessAndStatInfo(::pid_t pid,
                                   ProcessInstanceInfo &process_info,
                                   ProcessState &State, ::pid_t &tracerpid) {
-  ::pid_t tgid;
   tracerpid = 0;
   process_info.Clear();
 
@@ -220,7 +214,7 @@
   GetProcessEnviron(pid, process_info);
 
   // Get User and Group IDs and get tracer pid.
-  if (!GetStatusInfo(pid, process_info, State, tracerpid, tgid))
+  if (!GetStatusInfo(pid, process_info, State, tracerpid))
     return false;
 
   return true;
@@ -314,14 +308,3 @@
 Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
   return Status("unimplemented");
 }
-
-llvm::Optional<lldb::pid_t> lldb_private::getPIDForTID(lldb::pid_t tid) {
-  ::pid_t tracerpid, tgid = LLDB_INVALID_PROCESS_ID;
-  ProcessInstanceInfo process_info;
-  ProcessState state;
-
-  if (!GetStatusInfo(tid, process_info, state, tracerpid, tgid) ||
-      tgid == LLDB_INVALID_PROCESS_ID)
-    return llvm::None;
-  return tgid;
-}
diff --git a/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
index 5e37167..5961ff4 100644
--- a/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.cpp
@@ -247,19 +247,6 @@
     return;
   }
 
-  if (info.pl_flags & PL_FLAG_FORKED) {
-    MonitorClone(info.pl_child_pid);
-    return;
-  }
-
-  if (info.pl_flags & PL_FLAG_VFORK_DONE) {
-    Status error =
-        PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
-    if (error.Fail())
-      SetState(StateType::eStateInvalid);
-    return;
-  }
-
   if (info.pl_lwpid > 0) {
     for (const auto &t : m_threads) {
       if (t->GetID() == static_cast<lldb::tid_t>(info.pl_lwpid))
@@ -718,17 +705,17 @@
 
 void NativeProcessFreeBSD::SigchldHandler() {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+  // Process all pending waitpid notifications.
   int status;
   ::pid_t wait_pid =
       llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
 
   if (wait_pid == 0)
-    return;
+    return; // We are done.
 
   if (wait_pid == -1) {
     Status error(errno, eErrorTypePOSIX);
     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
-    return;
   }
 
   WaitStatus wait_status = WaitStatus::Decode(status);
@@ -898,7 +885,7 @@
       PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
   if (status.Fail())
     return status;
-  events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK;
+  events |= PTRACE_LWP;
   status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
   if (status.Fail())
     return status;
@@ -932,53 +919,3 @@
 bool NativeProcessFreeBSD::SupportHardwareSingleStepping() const {
   return !m_arch.IsMIPS();
 }
-
-void NativeProcessFreeBSD::MonitorClone(::pid_t child_pid) {
-  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-  LLDB_LOG(log, "fork, child_pid={0}", child_pid);
-
-  int status;
-  ::pid_t wait_pid =
-      llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
-  if (wait_pid != child_pid) {
-    LLDB_LOG(log,
-             "waiting for pid {0} failed. Assuming the pid has "
-             "disappeared in the meantime",
-             child_pid);
-    return;
-  }
-  if (WIFEXITED(status)) {
-    LLDB_LOG(log,
-             "waiting for pid {0} returned an 'exited' event. Not "
-             "tracking it.",
-             child_pid);
-    return;
-  }
-
-  MainLoop unused_loop;
-  NativeProcessFreeBSD child_process{static_cast<::pid_t>(child_pid),
-                                     m_terminal_fd, m_delegate, m_arch,
-                                     unused_loop};
-  child_process.ReinitializeThreads();
-  auto *child_thread =
-      static_cast<NativeThreadFreeBSD *>(child_process.GetCurrentThread());
-  assert(child_thread);
-  // new processes inherit dbregs, so we need to clear them
-  llvm::Error error = child_thread->GetRegisterContext().ClearDBRegs();
-  if (error) {
-    LLDB_LOG_ERROR(log, std::move(error),
-                   "failed to clear dbregs in forked process {1}: {0}",
-                   child_pid);
-    SetState(StateType::eStateInvalid);
-    return;
-  }
-
-  child_process.Detach();
-  Status pt_error =
-      PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
-  if (pt_error.Fail()) {
-    LLDB_LOG_ERROR(log, pt_error.ToError(),
-                   "unable to resume parent process {1}: {0}", GetID());
-    SetState(StateType::eStateInvalid);
-  }
-}
diff --git a/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
index 3ed5f74..ceffc37 100644
--- a/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/NativeProcessFreeBSD.h
@@ -113,7 +113,6 @@
   void MonitorSIGSTOP(lldb::pid_t pid);
   void MonitorSIGTRAP(lldb::pid_t pid);
   void MonitorSignal(lldb::pid_t pid, int signal);
-  void MonitorClone(::pid_t child_pid);
 
   Status PopulateMemoryRegionCache();
   void SigchldHandler();
diff --git a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
index cf2afcf..0000484 100644
--- a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD.h
@@ -32,8 +32,6 @@
   virtual llvm::Error
   CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) = 0;
 
-  virtual llvm::Error ClearDBRegs() { return llvm::Error::success(); }
-
 protected:
   virtual NativeProcessFreeBSD &GetProcess();
   virtual ::pid_t GetProcessPid();
diff --git a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
index 74abf24..e98e0a8 100644
--- a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -285,19 +285,4 @@
 #endif
 }
 
-llvm::Error NativeRegisterContextFreeBSD_arm64::ClearDBRegs() {
-#ifdef LLDB_HAS_FREEBSD_WATCHPOINT
-  if (llvm::Error error = ReadHardwareDebugInfo())
-    return error;
-
-  for (uint32_t i = 0; i < m_max_hbp_supported; i++)
-    m_hbp_regs[i].control = 0;
-  for (uint32_t i = 0; i < m_max_hwp_supported; i++)
-    m_hwp_regs[i].control = 0;
-  return WriteHardwareDebugRegs(eDREGTypeWATCH);
-#else
-  return llvm::error::success();
-#endif
-}
-
 #endif // defined (__aarch64__)
diff --git a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
index ae6f574..a230f8f 100644
--- a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
+++ b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.h
@@ -58,8 +58,6 @@
   llvm::Error
   CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
 
-  llvm::Error ClearDBRegs() override;
-
 private:
   // Due to alignment, FreeBSD reg/fpreg are a few bytes larger than
   // LLDB's GPR/FPU structs.  However, all fields have matching offsets
diff --git a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
index 5415b49..9328d60 100644
--- a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
+++ b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.cpp
@@ -653,10 +653,4 @@
   return YMMSplitPtr{&fpreg->sv_xmm[reg_index], &ymmreg[reg_index]};
 }
 
-llvm::Error NativeRegisterContextFreeBSD_x86_64::ClearDBRegs() {
-  uint64_t zero = 0;
-  RegisterValue dr7{zero};
-  return WriteRegister(GetDR(7), dr7).ToError();
-}
-
 #endif // defined(__x86_64__)
diff --git a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
index e4932c9..efd0f91 100644
--- a/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
+++ b/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_x86_64.h
@@ -55,8 +55,6 @@
   llvm::Error
   CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
 
-  llvm::Error ClearDBRegs() override;
-
 private:
   // Private member types.
   enum RegSetKind {
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 4880d4d..5a876ce 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -30,7 +30,6 @@
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/ThreadLauncher.h"
 #include "lldb/Host/common/NativeRegisterContext.h"
-#include "lldb/Host/linux/Host.h"
 #include "lldb/Host/linux/Ptrace.h"
 #include "lldb/Host/linux/Uio.h"
 #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
@@ -384,22 +383,14 @@
   ptrace_opts |= PTRACE_O_TRACEEXIT;
 
   // Have the tracer trace threads which spawn in the inferior process.
+  // TODO: if we want to support tracing the inferiors' child, add the
+  // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
   ptrace_opts |= PTRACE_O_TRACECLONE;
 
   // Have the tracer notify us before execve returns (needed to disable legacy
   // SIGTRAP generation)
   ptrace_opts |= PTRACE_O_TRACEEXEC;
 
-  // Have the tracer trace forked children.
-  ptrace_opts |= PTRACE_O_TRACEFORK;
-
-  // Have the tracer trace vforks.
-  ptrace_opts |= PTRACE_O_TRACEVFORK;
-
-  // Have the tracer trace vfork-done in order to restore breakpoints after
-  // the child finishes sharing memory.
-  ptrace_opts |= PTRACE_O_TRACEVFORKDONE;
-
   return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
 }
 
@@ -453,7 +444,8 @@
     LLDB_LOG(log, "tid {0}, si_code: {1}, si_pid: {2}", pid, info.si_code,
              info.si_pid);
 
-    MonitorClone(pid, llvm::None);
+    NativeThreadLinux &thread = AddThread(pid, /*resume*/ true);
+    ThreadWasCreated(thread);
     return;
   }
 
@@ -517,24 +509,29 @@
   }
 }
 
-void NativeProcessLinux::WaitForCloneNotification(::pid_t pid) {
+void NativeProcessLinux::WaitForNewThread(::pid_t tid) {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
 
-  // The PID is not tracked yet, let's wait for it to appear.
+  if (GetThreadByID(tid)) {
+    // We are already tracking the thread - we got the event on the new thread
+    // (see MonitorSignal) before this one. We are done.
+    return;
+  }
+
+  // The thread is not tracked yet, let's wait for it to appear.
   int status = -1;
   LLDB_LOG(log,
-           "received clone event for pid {0}. pid not tracked yet, "
-           "waiting for it to appear...",
-           pid);
-  ::pid_t wait_pid =
-      llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &status, __WALL);
-  // Since we are waiting on a specific pid, this must be the creation event.
+           "received thread creation event for tid {0}. tid not tracked "
+           "yet, waiting for thread to appear...",
+           tid);
+  ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, &status, __WALL);
+  // Since we are waiting on a specific tid, this must be the creation event.
   // But let's do some checks just in case.
-  if (wait_pid != pid) {
+  if (wait_pid != tid) {
     LLDB_LOG(log,
-             "waiting for pid {0} failed. Assuming the pid has "
+             "waiting for tid {0} failed. Assuming the thread has "
              "disappeared in the meantime",
-             pid);
+             tid);
     // The only way I know of this could happen is if the whole process was
     // SIGKILLed in the mean time. In any case, we can't do anything about that
     // now.
@@ -542,15 +539,17 @@
   }
   if (WIFEXITED(status)) {
     LLDB_LOG(log,
-             "waiting for pid {0} returned an 'exited' event. Not "
-             "tracking it.",
-             pid);
+             "waiting for tid {0} returned an 'exited' event. Not "
+             "tracking the thread.",
+             tid);
     // Also a very improbable event.
-    m_pending_pid_map.erase(pid);
     return;
   }
 
-  MonitorClone(pid, llvm::None);
+  LLDB_LOG(log, "pid = {0}: tracking new thread tid {1}", GetID(), tid);
+  NativeThreadLinux &new_thread = AddThread(tid, /*resume*/ true);
+
+  ThreadWasCreated(new_thread);
 }
 
 void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
@@ -561,26 +560,26 @@
   assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
 
   switch (info.si_code) {
-  case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
-  case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+  // TODO: these two cases are required if we want to support tracing of the
+  // inferiors' children.  We'd need this to debug a monitor. case (SIGTRAP |
+  // (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+
   case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
-    // This can either mean a new thread or a new process spawned via
-    // clone(2) without SIGCHLD or CLONE_VFORK flag.  Note that clone(2)
-    // can also cause PTRACE_EVENT_FORK and PTRACE_EVENT_VFORK if one
-    // of these flags are passed.
+    // This is the notification on the parent thread which informs us of new
+    // thread creation. We don't want to do anything with the parent thread so
+    // we just resume it. In case we want to implement "break on thread
+    // creation" functionality, we would need to stop here.
 
     unsigned long event_message = 0;
     if (GetEventMessage(thread.GetID(), &event_message).Fail()) {
       LLDB_LOG(log,
-               "pid {0} received clone() event but GetEventMessage failed "
-               "so we don't know the new pid/tid",
+               "pid {0} received thread creation event but "
+               "GetEventMessage failed so we don't know the new tid",
                thread.GetID());
-      ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
-    } else {
-      if (!MonitorClone(event_message, {{(info.si_code >> 8), thread.GetID()}}))
-        WaitForCloneNotification(event_message);
-    }
+    } else
+      WaitForNewThread(event_message);
 
+    ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
     break;
   }
 
@@ -646,11 +645,6 @@
     break;
   }
 
-  case (SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)): {
-    ResumeThread(thread, thread.GetState(), LLDB_INVALID_SIGNAL_NUMBER);
-    break;
-  }
-
   case 0:
   case TRAP_TRACE:  // We receive this on single stepping.
   case TRAP_HWBKPT: // We receive this on watchpoint hit
@@ -860,79 +854,6 @@
   StopRunningThreads(thread.GetID());
 }
 
-bool NativeProcessLinux::MonitorClone(
-    lldb::pid_t child_pid,
-    llvm::Optional<NativeProcessLinux::CloneInfo> clone_info) {
-  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-  LLDB_LOG(log, "clone, child_pid={0}, clone info?={1}", child_pid,
-           clone_info.hasValue());
-
-  auto find_it = m_pending_pid_map.find(child_pid);
-  if (find_it == m_pending_pid_map.end()) {
-    // not in the map, so this is the first signal for the PID
-    m_pending_pid_map.insert({child_pid, clone_info});
-    return false;
-  }
-  m_pending_pid_map.erase(find_it);
-
-  // second signal for the pid
-  assert(clone_info.hasValue() != find_it->second.hasValue());
-  if (!clone_info) {
-    // child signal does not indicate the event, so grab the one stored
-    // earlier
-    clone_info = find_it->second;
-  }
-
-  LLDB_LOG(log, "second signal for child_pid={0}, parent_tid={1}, event={2}",
-           child_pid, clone_info->parent_tid, clone_info->event);
-
-  auto *parent_thread = GetThreadByID(clone_info->parent_tid);
-  assert(parent_thread);
-
-  switch (clone_info->event) {
-  case PTRACE_EVENT_CLONE: {
-    // PTRACE_EVENT_CLONE can either mean a new thread or a new process.
-    // Try to grab the new process' PGID to figure out which one it is.
-    // If PGID is the same as the PID, then it's a new process.  Otherwise,
-    // it's a thread.
-    auto tgid_ret = getPIDForTID(child_pid);
-    if (tgid_ret != child_pid) {
-      // A new thread should have PGID matching our process' PID.
-      assert(!tgid_ret || tgid_ret.getValue() == GetID());
-
-      NativeThreadLinux &child_thread = AddThread(child_pid, /*resume*/ true);
-      // Resume the newly created thread.
-      ResumeThread(child_thread, eStateRunning, LLDB_INVALID_SIGNAL_NUMBER);
-      ThreadWasCreated(child_thread);
-
-      // Resume the parent.
-      ResumeThread(*parent_thread, parent_thread->GetState(),
-                   LLDB_INVALID_SIGNAL_NUMBER);
-      break;
-    }
-  }
-    LLVM_FALLTHROUGH;
-  case PTRACE_EVENT_FORK:
-  case PTRACE_EVENT_VFORK: {
-    MainLoop unused_loop;
-    NativeProcessLinux child_process{static_cast<::pid_t>(child_pid),
-                                     m_terminal_fd,
-                                     m_delegate,
-                                     m_arch,
-                                     unused_loop,
-                                     {static_cast<::pid_t>(child_pid)}};
-    child_process.Detach();
-    ResumeThread(*parent_thread, parent_thread->GetState(),
-                 LLDB_INVALID_SIGNAL_NUMBER);
-    break;
-  }
-  default:
-    llvm_unreachable("unknown clone_info.event");
-  }
-
-  return true;
-}
-
 bool NativeProcessLinux::SupportHardwareSingleStepping() const {
   if (m_arch.GetMachine() == llvm::Triple::arm || m_arch.IsMIPS())
     return false;
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h
index 86f6a1c..77905a1 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -157,7 +157,7 @@
 
   void MonitorCallback(lldb::pid_t pid, bool exited, WaitStatus status);
 
-  void WaitForCloneNotification(::pid_t pid);
+  void WaitForNewThread(::pid_t tid);
 
   void MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thread);
 
@@ -234,21 +234,6 @@
 
   /// Manages Intel PT process and thread traces.
   IntelPTManager m_intel_pt_manager;
-
-  struct CloneInfo {
-    int event;
-    lldb::tid_t parent_tid;
-  };
-
-  // Map of child processes that have been signaled once, and we are
-  // waiting for the second signal.
-  llvm::DenseMap<lldb::pid_t, llvm::Optional<CloneInfo>> m_pending_pid_map;
-
-  // Handle a clone()-like event.  If received by parent, clone_info contains
-  // additional info.  Returns true if the event is handled, or false if it
-  // is pending second notification.
-  bool MonitorClone(lldb::pid_t child_pid,
-                    llvm::Optional<CloneInfo> clone_info);
 };
 
 } // namespace process_linux
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 1f357e3..57f0eb3 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -256,24 +256,6 @@
     SetState(StateType::eStateStopped, true);
     return;
   }
-  case TRAP_CHLD: {
-    ptrace_state_t pst;
-    Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
-    if (error.Fail()) {
-      SetState(StateType::eStateInvalid);
-      return;
-    }
-
-    if (pst.pe_report_event == PTRACE_VFORK_DONE) {
-      Status error =
-          PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
-      if (error.Fail())
-        SetState(StateType::eStateInvalid);
-      return;
-    } else
-      MonitorClone(pst.pe_other_pid);
-    return;
-  }
   case TRAP_LWP: {
     ptrace_state_t pst;
     Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
@@ -528,7 +510,7 @@
   if (GetID() == LLDB_INVALID_PROCESS_ID)
     return error;
 
-  return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));
+  return PtraceWrapper(PT_DETACH, GetID());
 }
 
 Status NativeProcessNetBSD::Signal(int signo) {
@@ -756,17 +738,17 @@
 
 void NativeProcessNetBSD::SigchldHandler() {
   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
+  // Process all pending waitpid notifications.
   int status;
   ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
                                                  WALLSIG | WNOHANG);
 
   if (wait_pid == 0)
-    return;
+    return; // We are done.
 
   if (wait_pid == -1) {
     Status error(errno, eErrorTypePOSIX);
     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
-    return;
   }
 
   WaitStatus wait_status = WaitStatus::Decode(status);
@@ -954,9 +936,8 @@
       PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
   if (status.Fail())
     return status;
-  // TODO: PTRACE_POSIX_SPAWN?
-  events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
-                         PTRACE_VFORK | PTRACE_VFORK_DONE;
+  // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
+  events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
   status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
   if (status.Fail())
     return status;
@@ -993,39 +974,3 @@
 
   return error;
 }
-
-void NativeProcessNetBSD::MonitorClone(::pid_t child_pid) {
-  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-  LLDB_LOG(log, "clone, child_pid={0}", child_pid);
-
-  int status;
-  ::pid_t wait_pid =
-      llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
-  if (wait_pid != child_pid) {
-    LLDB_LOG(log,
-             "waiting for pid {0} failed. Assuming the pid has "
-             "disappeared in the meantime",
-             child_pid);
-    return;
-  }
-  if (WIFEXITED(status)) {
-    LLDB_LOG(log,
-             "waiting for pid {0} returned an 'exited' event. Not "
-             "tracking it.",
-             child_pid);
-    return;
-  }
-
-  MainLoop unused_loop;
-  NativeProcessNetBSD child_process{static_cast<::pid_t>(child_pid),
-                                    m_terminal_fd, m_delegate, m_arch,
-                                    unused_loop};
-  child_process.Detach();
-  Status pt_error =
-      PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
-  if (pt_error.Fail()) {
-    LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
-                   "unable to resume parent process {1}: {0}", GetID());
-    SetState(StateType::eStateInvalid);
-  }
-}
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 3384078..3d59a4f 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -106,7 +106,6 @@
   void MonitorSIGSTOP(lldb::pid_t pid);
   void MonitorSIGTRAP(lldb::pid_t pid);
   void MonitorSignal(lldb::pid_t pid, int signal);
-  void MonitorClone(::pid_t child_pid);
 
   Status PopulateMemoryRegionCache();
   void SigchldHandler();
diff --git a/test/API/functionalities/gdb_remote_client/TestMultiprocess.py b/test/API/functionalities/gdb_remote_client/TestMultiprocess.py
index 551bf72..baf9f9c 100644
--- a/test/API/functionalities/gdb_remote_client/TestMultiprocess.py
+++ b/test/API/functionalities/gdb_remote_client/TestMultiprocess.py
@@ -1,5 +1,6 @@
 from __future__ import print_function
 import lldb
+import unittest
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test.decorators import *
 from gdbclientutils import *
diff --git a/test/Shell/Subprocess/Inputs/fork.cpp b/test/Shell/Subprocess/Inputs/fork.cpp
deleted file mode 100644
index 4424293..0000000
--- a/test/Shell/Subprocess/Inputs/fork.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <assert.h>
-#if defined(TEST_CLONE)
-#include <sched.h>
-#endif
-#include <stdint.h>
-#include <stdio.h>
-#include <unistd.h>
-
-int g_val = 0;
-
-void parent_func() {
-  g_val = 1;
-  printf("function run in parent\n");
-}
-
-int child_func(void *unused) {
-  // we need to avoid memory modifications for vfork(), yet we want
-  // to be able to test watchpoints, so do the next best thing
-  // and restore the original value
-  g_val = 2;
-  g_val = 0;
-  return 0;
-}
-
-int main() {
-  alignas(uintmax_t) char stack[4096];
-
-#if defined(TEST_CLONE)
-  pid_t pid = clone(child_func, &stack[sizeof(stack)], 0, NULL);
-#elif defined(TEST_FORK)
-  pid_t pid = TEST_FORK();
-  if (pid == 0)
-    _exit(child_func(NULL));
-#endif
-  assert(pid != -1);
-
-  parent_func();
-  int status, wait_flags = 0;
-#if defined(TEST_CLONE)
-  wait_flags = __WALL;
-#endif
-  pid_t waited = waitpid(pid, &status, wait_flags);
-  assert(waited == pid);
-  assert(WIFEXITED(status));
-  printf("child exited: %d\n", WEXITSTATUS(status));
-
-  return 0;
-}
diff --git a/test/Shell/Subprocess/clone-follow-parent-wp.test b/test/Shell/Subprocess/clone-follow-parent-wp.test
deleted file mode 100644
index 67d94af..0000000
--- a/test/Shell/Subprocess/clone-follow-parent-wp.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# REQUIRES: native && (system-linux || system-netbsd) && dbregs-set
-# clone() tests fails on arm64 Linux, PR #49899
-# UNSUPPORTED: system-linux && target-aarch64
-# RUN: %clangxx_host -g %p/Inputs/fork.cpp -DTEST_CLONE -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-process launch -s
-watchpoint set variable -w write g_val
-# CHECK: Watchpoint created:
-continue
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = watchpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0
diff --git a/test/Shell/Subprocess/clone-follow-parent.test b/test/Shell/Subprocess/clone-follow-parent.test
deleted file mode 100644
index 3d89279..0000000
--- a/test/Shell/Subprocess/clone-follow-parent.test
+++ /dev/null
@@ -1,12 +0,0 @@
-# REQUIRES: native && (system-linux || system-netbsd)
-# clone() tests fails on arm64 Linux, PR #49899
-# UNSUPPORTED: system-linux && target-aarch64
-# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_CLONE -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-b parent_func
-process launch
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = breakpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0
diff --git a/test/Shell/Subprocess/fork-follow-parent-wp.test b/test/Shell/Subprocess/fork-follow-parent-wp.test
deleted file mode 100644
index cde5b41..0000000
--- a/test/Shell/Subprocess/fork-follow-parent-wp.test
+++ /dev/null
@@ -1,13 +0,0 @@
-# REQUIRES: native && dbregs-set
-# UNSUPPORTED: system-windows
-# RUN: %clangxx_host -g %p/Inputs/fork.cpp -DTEST_FORK=fork -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-process launch -s
-watchpoint set variable -w write g_val
-# CHECK: Watchpoint created:
-continue
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = watchpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0
diff --git a/test/Shell/Subprocess/fork-follow-parent.test b/test/Shell/Subprocess/fork-follow-parent.test
deleted file mode 100644
index 1ffc2cb..0000000
--- a/test/Shell/Subprocess/fork-follow-parent.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# REQUIRES: native
-# UNSUPPORTED: system-windows
-# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_FORK=fork -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-b parent_func
-process launch
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = breakpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0
diff --git a/test/Shell/Subprocess/lit.local.cfg b/test/Shell/Subprocess/lit.local.cfg
deleted file mode 100644
index c9b378b..0000000
--- a/test/Shell/Subprocess/lit.local.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-if 'lldb-repro' in config.available_features:
-  config.unsupported = True
diff --git a/test/Shell/Subprocess/vfork-follow-parent-wp.test b/test/Shell/Subprocess/vfork-follow-parent-wp.test
deleted file mode 100644
index 8c74e28..0000000
--- a/test/Shell/Subprocess/vfork-follow-parent-wp.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# REQUIRES: native && dbregs-set
-# UNSUPPORTED: system-windows
-# UNSUPPORTED: system-darwin
-# RUN: %clangxx_host -g %p/Inputs/fork.cpp -DTEST_FORK=vfork -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-process launch -s
-watchpoint set variable -w write g_val
-# CHECK: Watchpoint created:
-continue
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = watchpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0
diff --git a/test/Shell/Subprocess/vfork-follow-parent.test b/test/Shell/Subprocess/vfork-follow-parent.test
deleted file mode 100644
index 6d9850a..0000000
--- a/test/Shell/Subprocess/vfork-follow-parent.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# REQUIRES: native
-# UNSUPPORTED: system-windows
-# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_FORK=vfork -o %t
-# RUN: %lldb -b -s %s %t | FileCheck %s
-b parent_func
-process launch
-# CHECK-NOT: function run in parent
-# CHECK: stop reason = breakpoint
-continue
-# CHECK: function run in parent
-# CHECK: child exited: 0