[Lldb-commits] [lldb] [lldb] Reland stop-on-fork and stop-on-vfork settings (#188710) (PR #208165)

2026-07-08 Thread Sergei Druzhkov via lldb-commits

https://github.com/DrSergei updated 
https://github.com/llvm/llvm-project/pull/208165

>From 3f6198d5e448086956fd1108d7fd3145c728b189 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov 
Date: Sat, 4 Jul 2026 13:49:50 +0300
Subject: [PATCH] [lldb] Reland stop-on-fork and stop-on-vfork settings

Added support for new `target.process.stop-on-fork` and
`target.process.stop-on-vfork` settings. GDB already has ability to set
[catchpoints](https://www.sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html)
on `fork` and `vfork`, so having this feature in LLDB might be useful
(e.g. use it to get pid of new process and attach to the new process
from different console).
---
 lldb/include/lldb/Target/Process.h|  2 +
 lldb/source/Target/Process.cpp| 12 
 lldb/source/Target/StopInfo.cpp   | 14 ++--
 lldb/source/Target/TargetProperties.td|  8 +++
 .../API/functionalities/fork/stop/Makefile|  3 +
 .../fork/stop/TestStopOnForkAndVFork.py   | 70 +++
 .../test/API/functionalities/fork/stop/main.c | 18 +
 lldb/test/Shell/Subprocess/stop-on-fork.test  | 12 
 lldb/test/Shell/Subprocess/stop-on-vfork.test | 12 
 9 files changed, 145 insertions(+), 6 deletions(-)
 create mode 100644 lldb/test/API/functionalities/fork/stop/Makefile
 create mode 100644 
lldb/test/API/functionalities/fork/stop/TestStopOnForkAndVFork.py
 create mode 100644 lldb/test/API/functionalities/fork/stop/main.c
 create mode 100644 lldb/test/Shell/Subprocess/stop-on-fork.test
 create mode 100644 lldb/test/Shell/Subprocess/stop-on-vfork.test

diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index 7b1424e6dfa59..80b3fa300971f 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -108,6 +108,8 @@ class ProcessProperties : public Properties {
   bool GetWarningsOptimization() const;
   bool GetWarningsUnsupportedLanguage() const;
   bool GetStopOnExec() const;
+  bool GetStopOnFork() const;
+  bool GetStopOnVFork() const;
   std::chrono::seconds GetUtilityExpressionTimeout() const;
   std::chrono::seconds GetInterruptTimeout() const;
   bool GetOSPluginReportsAllThreads() const;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 4360250b21475..d929f45419783 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -343,6 +343,18 @@ bool ProcessProperties::GetUseDelayedBreakpoints() const {
   idx, g_process_properties[idx].default_uint_value != 0);
 }
 
+bool ProcessProperties::GetStopOnFork() const {
+  const uint32_t idx = ePropertyStopOnFork;
+  return GetPropertyAtIndexAs(
+  idx, g_process_properties[idx].default_uint_value != 0);
+}
+
+bool ProcessProperties::GetStopOnVFork() const {
+  const uint32_t idx = ePropertyStopOnVFork;
+  return GetPropertyAtIndexAs(
+  idx, g_process_properties[idx].default_uint_value != 0);
+}
+
 std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
   const uint32_t idx = ePropertyUtilityExpressionTimeout;
   uint64_t value = GetPropertyAtIndexAs(
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index c20b0ed07ee3c..80d7b3b4c2c01 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -1545,8 +1545,8 @@ class StopInfoFork : public StopInfo {
   bool ShouldStop(Event *event_ptr) override {
 // During expression evaluation, return true so that the fork event
 // reaches RunThreadPlan as a real stop (not auto-restarted by
-// DoOnRemoval). RunThreadPlan decides whether to stop or continue
-// based on the stop-on-fork option.
+// DoOnRemoval) or target.process.stop-on-fork is true. RunThreadPlan
+// decides whether to stop or continue based on the stop-on-fork option.
 //
 // We check per-thread (not just process-wide IsRunningExpression)
 // because other threads may fork concurrently after the
@@ -1554,8 +1554,9 @@ class StopInfoFork : public StopInfo {
 ThreadSP thread_sp(m_thread_wp.lock());
 if (thread_sp) {
   ProcessSP process_sp = thread_sp->GetProcess();
-  if (process_sp && process_sp->GetModIDRef().IsRunningExpression() &&
-  thread_sp->IsRunningCallFunctionPlan())
+  if (process_sp && ((process_sp->GetModIDRef().IsRunningExpression() &&
+  thread_sp->IsRunningCallFunctionPlan()) ||
+ process_sp->GetStopOnFork()))
 return true;
 }
 return false;
@@ -1610,8 +1611,9 @@ class StopInfoVFork : public StopInfo {
 ThreadSP thread_sp(m_thread_wp.lock());
 if (thread_sp) {
   ProcessSP process_sp = thread_sp->GetProcess();
-  if (process_sp && process_sp->GetModIDRef().IsRunningExpression() &&
-  thread_sp->IsRunningCallFunctionPlan())
+  if (process_sp && ((process_sp->GetModIDRef().IsRunningExpression() &&
+  thread_sp->IsRunning

[Lldb-commits] [lldb] [lldb] Reland stop-on-fork and stop-on-vfork settings (#188710) (PR #208165)

2026-07-08 Thread Sergei Druzhkov via lldb-commits

https://github.com/DrSergei created 
https://github.com/llvm/llvm-project/pull/208165

Added support for new `target.process.stop-on-fork` and 
`target.process.stop-on-vfork` settings. GDB already has ability to set 
[catchpoints](https://www.sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html)
 on `fork` and `vfork`, so having this feature in LLDB might be useful (e.g. 
use it to get pid of new process and attach to the new process from different 
console).

>From 55088a780026ca177c4e831d773fc1a9955fbd71 Mon Sep 17 00:00:00 2001
From: Sergei Druzhkov 
Date: Sat, 4 Jul 2026 13:49:50 +0300
Subject: [PATCH] [lldb] Reland stop-on-fork and stop-on-vfork settings
 (#188710)

Added support for new `target.process.stop-on-fork` and
`target.process.stop-on-vfork` settings. GDB already has ability to set
[catchpoints](https://www.sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html)
on `fork` and `vfork`, so having this feature in LLDB might be useful
(e.g. use it to get pid of new process and attach to the new process
from different console).
---
 lldb/include/lldb/Target/Process.h|  2 +
 lldb/source/Target/Process.cpp| 12 
 lldb/source/Target/StopInfo.cpp   | 14 ++--
 lldb/source/Target/TargetProperties.td|  8 +++
 .../API/functionalities/fork/stop/Makefile|  3 +
 .../fork/stop/TestStopOnForkAndVFork.py   | 70 +++
 .../test/API/functionalities/fork/stop/main.c | 18 +
 lldb/test/Shell/Subprocess/stop-on-fork.test  | 12 
 lldb/test/Shell/Subprocess/stop-on-vfork.test | 12 
 9 files changed, 145 insertions(+), 6 deletions(-)
 create mode 100644 lldb/test/API/functionalities/fork/stop/Makefile
 create mode 100644 
lldb/test/API/functionalities/fork/stop/TestStopOnForkAndVFork.py
 create mode 100644 lldb/test/API/functionalities/fork/stop/main.c
 create mode 100644 lldb/test/Shell/Subprocess/stop-on-fork.test
 create mode 100644 lldb/test/Shell/Subprocess/stop-on-vfork.test

diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index 7b1424e6dfa59..80b3fa300971f 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -108,6 +108,8 @@ class ProcessProperties : public Properties {
   bool GetWarningsOptimization() const;
   bool GetWarningsUnsupportedLanguage() const;
   bool GetStopOnExec() const;
+  bool GetStopOnFork() const;
+  bool GetStopOnVFork() const;
   std::chrono::seconds GetUtilityExpressionTimeout() const;
   std::chrono::seconds GetInterruptTimeout() const;
   bool GetOSPluginReportsAllThreads() const;
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 4360250b21475..d929f45419783 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -343,6 +343,18 @@ bool ProcessProperties::GetUseDelayedBreakpoints() const {
   idx, g_process_properties[idx].default_uint_value != 0);
 }
 
+bool ProcessProperties::GetStopOnFork() const {
+  const uint32_t idx = ePropertyStopOnFork;
+  return GetPropertyAtIndexAs(
+  idx, g_process_properties[idx].default_uint_value != 0);
+}
+
+bool ProcessProperties::GetStopOnVFork() const {
+  const uint32_t idx = ePropertyStopOnVFork;
+  return GetPropertyAtIndexAs(
+  idx, g_process_properties[idx].default_uint_value != 0);
+}
+
 std::chrono::seconds ProcessProperties::GetUtilityExpressionTimeout() const {
   const uint32_t idx = ePropertyUtilityExpressionTimeout;
   uint64_t value = GetPropertyAtIndexAs(
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index c20b0ed07ee3c..80d7b3b4c2c01 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -1545,8 +1545,8 @@ class StopInfoFork : public StopInfo {
   bool ShouldStop(Event *event_ptr) override {
 // During expression evaluation, return true so that the fork event
 // reaches RunThreadPlan as a real stop (not auto-restarted by
-// DoOnRemoval). RunThreadPlan decides whether to stop or continue
-// based on the stop-on-fork option.
+// DoOnRemoval) or target.process.stop-on-fork is true. RunThreadPlan
+// decides whether to stop or continue based on the stop-on-fork option.
 //
 // We check per-thread (not just process-wide IsRunningExpression)
 // because other threads may fork concurrently after the
@@ -1554,8 +1554,9 @@ class StopInfoFork : public StopInfo {
 ThreadSP thread_sp(m_thread_wp.lock());
 if (thread_sp) {
   ProcessSP process_sp = thread_sp->GetProcess();
-  if (process_sp && process_sp->GetModIDRef().IsRunningExpression() &&
-  thread_sp->IsRunningCallFunctionPlan())
+  if (process_sp && ((process_sp->GetModIDRef().IsRunningExpression() &&
+  thread_sp->IsRunningCallFunctionPlan()) ||
+ process_sp->GetStopOnFork()))
 return true;
 }
 return false;
@@ -1610,8 +1611,9 @@ class Stop