From: Kurt Miller Subject: devel/gdb: updated p1 diff with addtional bug fix To: jca@wxcvbn.org, pascal@stumpf.co, ports@openbsd.org, tech@openbsd.org Date: Fri, 12 Dec 2025 16:09:36 +0000 This is a new version of gdb bug fixes. It now includes a fix for attaching to running processes to allow ^C to interrupt and bring the debugger back to the prompt. I also removed the ifdef guards on PT_PTS_NAMELEN to ensure p1 is built against base with that define. The issue with ^C on attached processes is that gdb clears the global inferior_ptid and installs the pass_signal handler for SIGINT on its way to calling waitpid. When SIGINT is received pass_signal was calling kill(0, SIGINT) which sends the signal to the process group of gdb. However, since we attached to an existing process in a different process group, we essentially sent SIGINT back to gdb, causing us to be suck in a SIGINT storm. After trying to understand how to fix this the right way, I eventually gave up and looked at what FreeBSD does. They have a hack for this that works for us too. In short this diff does the following: * Uses ptrace PT_GET_THREAD_* for both setting thread names and detecting if threads are still alive. The thread_alive detection fixes 'info threads' of processes whose threads exit while debugging. * Fixes SIGINT storm using patch from FreeBSD to direct the SIGINT to the current inferior process instead of gdb's process group. This allows ^C to bring us back to the gdb prompt on attached processes. okay? Index: Makefile =================================================================== RCS file: /cvs/ports/devel/gdb/Makefile,v diff -u -p -u -r1.98 Makefile --- Makefile 4 Dec 2025 18:28:32 -0000 1.98 +++ Makefile 12 Dec 2025 15:36:29 -0000 @@ -2,7 +2,7 @@ COMMENT= GNU debugger CATEGORIES= devel DISTNAME= gdb-16.3 -REVISION= 0 +REVISION= 1 HOMEPAGE= https://www.gnu.org/software/gdb/ Index: patches/patch-gdb_inflow_c =================================================================== RCS file: patches/patch-gdb_inflow_c diff -N patches/patch-gdb_inflow_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-gdb_inflow_c 12 Dec 2025 15:36:29 -0000 @@ -0,0 +1,17 @@ +Pass SIGINT to attached inferior + +Index: gdb/inflow.c +--- gdb/inflow.c.orig ++++ gdb/inflow.c +@@ -872,7 +872,10 @@ static void + pass_signal (int signo) + { + #ifndef _WIN32 +- kill (inferior_ptid.pid (), SIGINT); ++ if (inferior_ptid.pid ()) ++ kill (inferior_ptid.pid (), SIGINT); ++ else ++ kill (current_inferior ()->pid, SIGINT); + #endif + } + Index: patches/patch-gdb_obsd-nat_c =================================================================== RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_obsd-nat_c,v diff -u -p -u -r1.1 patch-gdb_obsd-nat_c --- patches/patch-gdb_obsd-nat_c 4 Dec 2025 18:28:32 -0000 1.1 +++ patches/patch-gdb_obsd-nat_c 12 Dec 2025 15:36:29 -0000 @@ -1,15 +1,9 @@ -Add support for thread_name. +Add support for thread_name and thread_alive using ptrace. Index: gdb/obsd-nat.c --- gdb/obsd-nat.c.orig +++ gdb/obsd-nat.c -@@ -23,11 +23,13 @@ - - #include - #include -+#include - #include "gdbsupport/gdb_wait.h" - +@@ -28,6 +28,7 @@ #include "inf-ptrace.h" #include "obsd-nat.h" #include "gdbsupport/eintr.h" @@ -17,48 +11,129 @@ Index: gdb/obsd-nat.c /* OpenBSD 5.2 and later include rthreads which uses a thread model that maps userland threads directly onto kernel threads in a 1:1 -@@ -183,4 +185,69 @@ int - obsd_nat_target::remove_fork_catchpoint (int pid) - { - return 0; -+} -+ +@@ -42,34 +43,78 @@ obsd_nat_target::pid_to_str (ptid_t ptid) + return normal_pid_to_str (ptid); + } + +-void +-obsd_nat_target::update_thread_list () +/* Generic thread lister within a specified PID. The CALLBACK + parameters is a C++ function that is called for each detected thread. + When the CALLBACK function returns true, the iteration is interrupted. + -+ This function assumes internally that the queried process is stopped -+ and the number of threads does not change between two sysctl () calls. */ ++ This function assumes internally that the queried process is stopped. */ + +static bool +obsd_thread_lister (const pid_t pid, -+ gdb::function_view ++ gdb::function_view + callback) -+{ -+ int mib[6] = {CTL_KERN, KERN_PROC, KERN_PROC_PID | KERN_PROC_SHOW_THREADS, -+ pid, sizeof(struct kinfo_proc), 0}; -+ size_t size; -+ -+ if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) -+ perror_with_name (("sysctl")); -+ -+ mib[5] = size / sizeof (struct kinfo_proc); -+ -+ gdb::unique_xmalloc_ptr ki -+ ((struct kinfo_proc *) xcalloc (mib[5], sizeof (struct kinfo_proc))); -+ -+ if (sysctl (mib, ARRAY_SIZE (mib), ki.get (), &size, NULL, 0) == -1 -+ || size == 0) -+ perror_with_name (("sysctl")); -+ -+ for (size_t i = 0; i < size / sizeof (struct kinfo_proc); i++) -+ { -+ struct kinfo_proc *l = &ki[i]; -+ if (callback (l)) + { +- pid_t pid = inferior_ptid.pid (); + struct ptrace_thread_state pts; + +- prune_threads (); +- + if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) + perror_with_name (("ptrace")); + + while (pts.pts_tid != -1) + { +- ptid_t ptid = ptid_t (pid, pts.pts_tid, 0); +- +- if (!in_thread_list (this, ptid)) +- { +- if (inferior_ptid.lwp () == 0) +- thread_change_ptid (this, inferior_ptid, ptid); +- else +- add_thread (this, ptid); +- } +- ++ if (callback (&pts)) + return true; -+ } + if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) + perror_with_name (("ptrace")); + } + + return false; + } + ++/* Fuction to support executing callback for each alive thread */ ++ ++static void ++for_each_thread (pid_t pid, gdb::function_view callback) ++{ ++ auto fn ++ = [=, &callback] (const struct ptrace_thread_state *pts) ++ { ++ ptid_t ptid = ptid_t (pid, pts->pts_tid, 0); ++ callback (ptid); ++ return false; ++ }; ++ ++ obsd_thread_lister (pid, fn); ++} ++ ++/* Implement the "post_attach" target_ops method. */ ++ ++static void ++obsd_add_threads (obsd_nat_target *target, pid_t pid) ++{ ++ auto fn ++ = [&target] (ptid_t ptid) ++ { ++ if (!in_thread_list (target, ptid)) ++ { ++ if (inferior_ptid.lwp () == 0) ++ thread_change_ptid (target, inferior_ptid, ptid); ++ else ++ add_thread (target, ptid); ++ } ++ }; ++ ++ for_each_thread (pid, fn); ++} ++ ++void ++obsd_nat_target::update_thread_list () ++{ ++ pid_t pid = inferior_ptid.pid (); ++ ++ prune_threads (); ++ obsd_add_threads (this, pid); ++} ++ + /* Enable additional event reporting on a new or existing process. */ + + static void +@@ -143,6 +188,7 @@ void + obsd_nat_target::post_attach (int pid) + { + obsd_enable_proc_events (pid); ++ obsd_add_threads (this, pid); + } + + /* Implement the virtual inf_ptrace_target::post_startup_inferior method. */ +@@ -183,4 +229,48 @@ int + obsd_nat_target::remove_fork_catchpoint (int pid) + { + return 0; ++} ++ ++/* See obsd-nat.h. */ ++ ++bool ++obsd_nat_target::thread_alive (ptid_t ptid) ++{ ++ pid_t pid = ptid.pid (); ++ ptid_t::lwp_type tid = ptid.lwp (); ++ ++ auto fn ++ = [=] (const struct ptrace_thread_state *pts) ++ { ++ return pts->pts_tid == tid; ++ }; ++ ++ return obsd_thread_lister (pid, fn); +} + +/* See obsd-nat.h. */ @@ -69,14 +144,14 @@ Index: gdb/obsd-nat.c + pid_t pid = thr->ptid.pid (); + ptid_t::lwp_type tid = thr->ptid.lwp (); + -+ static char buf[KI_MAXCOMLEN] = {}; ++ static char buf[PT_PTS_NAMELEN] = {}; + + auto fn -+ = [=] (const struct kinfo_proc *ki) ++ = [=] (const struct ptrace_thread_state *pts) + { -+ if (ki->p_tid == tid) ++ if (pts->pts_tid == tid) + { -+ xsnprintf (buf, sizeof buf, "%s", ki->p_name); ++ xsnprintf (buf, sizeof buf, "%s", pts->pts_name); + return true; + } + return false; Index: patches/patch-gdb_obsd-nat_h =================================================================== RCS file: /cvs/ports/devel/gdb/patches/patch-gdb_obsd-nat_h,v diff -u -p -u -r1.1 patch-gdb_obsd-nat_h --- patches/patch-gdb_obsd-nat_h 4 Dec 2025 18:28:32 -0000 1.1 +++ patches/patch-gdb_obsd-nat_h 12 Dec 2025 15:36:29 -0000 @@ -1,12 +1,13 @@ -Add support for thread_name. +Add support for thread_name and thread_alive. Index: gdb/obsd-nat.h --- gdb/obsd-nat.h.orig +++ gdb/obsd-nat.h -@@ -27,6 +27,7 @@ class obsd_nat_target : public inf_ptrace_target +@@ -27,6 +27,8 @@ class obsd_nat_target : public inf_ptrace_target /* Override some methods to support threads. */ std::string pid_to_str (ptid_t) override; void update_thread_list () override; ++ bool thread_alive (ptid_t ptid) override; + const char *thread_name (struct thread_info *thr) override; ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;