Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Simon Marchi <simark@simark.ca>
To: Matthieu Longo <matthieu.longo@arm.com>, gdb-patches@sourceware.org
Cc: Luis Machado <luis.machado@amd.com>,
	Luis Machado <luis.machado.foss@gmail.com>,
	Andrew Burgess <aburgess@redhat.com>,
	Yury Khrustalev <yury.khrustalev@arm.com>,
	Pedro Alves <pedro@palves.net>, Tom Tromey <tom@tromey.com>
Subject: Re: [PATCH v1 02/10] gdb: rely on the first alive thread TPID when reading Linux procfs files
Date: Thu, 9 Jul 2026 10:24:45 -0400	[thread overview]
Message-ID: <590655c1-abed-4a16-b8cc-762f1d8e6093@simark.ca> (raw)
In-Reply-To: <20260707154900.94542-3-matthieu.longo@arm.com>



On 2026-07-07 11:48, Matthieu Longo wrote:
> On Linux, /proc/<pid> is keyed by the thread-group leader PID. When
> the leader has exited, some /proc/<pid>/... entries become unavailable
> even though another thread is still alive. This can happen, for instance,
> when the main thread calls pthread_exit() and another thread continues
> the execution (existing test: gcore-stale-thread).
> 
> This causes GDB to fail to read procfs entries such as cmdline, cwd,
> exe, maps, and smaps when it uses 'current_inferior ()->pid' after the
> thread-group leader has exited.
> 
> Fix this by adding inferior::first_alive_thread(), which returns the
> PTID of the first non-exited thread of the inferior. Use its LWP ID
> when accessing procfs entries that only need a representative live LWP
> belonging to the process.
> 
> Update linux_info_proc, linux_process_address_in_memtag_page, and
> linux_find_memory_regions_full to use this live-thread LWP ID instead
> of the inferior PID when constructing procfs paths.

First comment, can we have a test for this?  I think it would be
straightforward to write.

This is an improvement, but I can still imagine some cases it would
fail.  A thread could have exited, gdb (or gdbserver) could have reaped
it status already, but the information might not have made it all the
way to the core yet.  So the "first alive thread" you select might not
actually be alive on the system.  I can't think of a way to fix that
problem generally, especially in the remote case.  If GDB checks in
advance "is this thread alive" and then tries to access is, I feel like
there will always be a TOCTOU problem.

I'm not opposed to merging a simple fix like this that takes care of the
most obvious cases (the main thread has exited, all threads are stopped,
and it obviously doesn't work).  But I think we should capture the
shortcomings we know about as comments in the code.

Then, I wondered if everything we access through /proc is going to give
the same response when we access them through another thread than the
leader.  I asked ChatGPT for a summary:

    Entry              Scope             Notes
    -----------------  ----------------  --------------------------------------
    cmdline            Process-wide      Same for all threads; comes from the
                                         shared address space (mm_struct).

    cwd                Per-thread        Usually shared, but can differ if
                                         threads use unshare(CLONE_FS).

    environ            Process-wide      Same for all threads; comes from the
                                         shared address space (mm_struct).

    exe                Process-wide      Same executable for all threads.

    maps               Process-wide      Describes the shared address space
                                         (mm_struct); same for all threads.

    status             Mixed             Contains both per-thread fields
                                         (Pid, State, SigPnd, etc.) and
                                         thread-group fields (VmSize, Threads,
                                         etc.).

    stat               Per-thread       Describes the specific task
                                         (/proc/<tid>/stat).

    smaps              Process-wide     Same mappings as maps; based on the
                                         shared address space.

    coredump_filter    Process-wide     Stored in the shared memory descriptor;
                                           same for all threads.

For most of the info it should be fine, as they are shared between all
threads.

For cwd, it's shared unless some threads call `unshared(CLONE_FS)`, I
don't know if it's common to do that.

For stat and status it looks a bit odd, because we print "process
<pid>", and then the line right below it (Process with a capital P),
which comes from /proc/<tid>/stat, gives a different number.

   (gdb) info proc stat
   process 1989928
   Process: 1991838
   Exec file: a.out
   State: t
   Parent process: 1989898
   Process group: 1989928
   Session id: 126340
   ...

In any case, we could perhaps improve the "process <pid>" line that we
print to indicate which thread we obtained the information from, in the
"auto-select a thread" case.

Finally, linux_fill_prpsinfo still uses the ptid.pid():

  pid = inferior_ptid.pid ();
  xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);

Should it be changed too?

And linux_address_in_shadow_stack_mem_range too?

Perhaps it would be useful to have a function "read me a whole file from
/proc" that takes an `inferior *` and returns a string, encapsulating
the logic of finding a thread to read from.

> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index 9c031035a23..305b1d31830 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -513,6 +513,15 @@ class inferior : public refcounted_object,
>    /* Find (non-exited) thread PTID of this inferior.  */
>    thread_info *find_thread (ptid_t ptid);
>  
> +  /* Return the first (non-exited) thread PTID of this inferior.
> +
> +     This method should be used in place of current_inferior ()->pid for any
> +     features relying only on the PID like the reading of procfs files.
> +     On Linux, /proc/<pid> is keyed by the thread-group leader PID. When the
> +     leader has exited, some /proc/<pid>/... entries become unavailable even
> +     though another thread is still alive.  */
> +  ptid_t first_alive_thread () const;

I think this comment is too specific to Linux and the problem at hand in
particular for this location.  It should just say "return the first
non-exited thread of the inferior" or something like that.

Function any_thread_of_inferior already does more or less what you want,
but it prefers the currently selected thread, which might not be what we
want (we perhaps want to prefer the leader).  That function could be
renamed to any_non_exited_thread_of_inferior to be clearer.

I would prefer if you renamed first_alive_thread to
first_non_exited_thread, that's the terminology we use elsewhere.
"live" makes me think of the "target_thread_alive" target function,
which actually pokes the target to see if the thread is alive right now,
that's different.

Simon

  parent reply	other threads:[~2026-07-09 14:25 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07 15:48 [PATCH v1 00/10] gdb: bugfix 31207 and various refactoring in linux-tdep Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 01/10] gdb/linux-tdep: change linux_fill_prpsinfo to return bool Matthieu Longo
2026-07-09  6:26   ` Thiago Jung Bauermann
2026-07-09 12:23     ` Simon Marchi
2026-07-27 14:38       ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 02/10] gdb: rely on the first alive thread TPID when reading Linux procfs files Matthieu Longo
2026-07-09  6:29   ` Thiago Jung Bauermann
2026-07-13  9:11     ` Matthieu Longo
2026-07-09 14:24   ` Simon Marchi [this message]
2026-07-14 15:47     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 03/10] target_fileio_read_stralloc: add an optional length parameter Matthieu Longo
2026-07-09  6:30   ` Thiago Jung Bauermann
2026-07-13 15:26     ` Matthieu Longo
2026-07-24  2:50       ` Thiago Jung Bauermann
2026-07-27 14:52         ` Matthieu Longo
2026-07-29  1:57           ` Thiago Jung Bauermann
2026-07-21 21:28   ` Luis
2026-07-27 14:48     ` Matthieu Longo
2026-07-27 14:53     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 04/10] gdb support: add gdb::replace algorithm for iterators and ranges Matthieu Longo
2026-07-09  6:30   ` Thiago Jung Bauermann
2026-07-10 21:21   ` Kevin Buettner
2026-07-13 15:51     ` Matthieu Longo
2026-07-21 21:33   ` Luis
2026-07-27 14:58     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 05/10] gdb: introduce helper class file_reader_t Matthieu Longo
2026-07-09  6:33   ` Thiago Jung Bauermann
2026-07-13 17:17     ` Matthieu Longo
2026-07-10 21:43   ` Kevin Buettner
2026-07-13 16:31     ` Matthieu Longo
2026-07-13 15:50   ` Schimpe, Christina
2026-07-13 17:12     ` Matthieu Longo
2026-07-22 16:36       ` Joos, Christina
2026-07-27 15:13         ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 06/10] gdb/linux-tdep: migrate linux_info_proc to file_reader_t Matthieu Longo
2026-07-09  6:35   ` Thiago Jung Bauermann
2026-07-13 17:20     ` Matthieu Longo
2026-07-21 21:43   ` Luis
2026-07-27 17:11     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 07/10] gdb/linux-tdep: migrate linux_find_memory_regions_full " Matthieu Longo
2026-07-09  6:36   ` Thiago Jung Bauermann
2026-07-14  8:40     ` Matthieu Longo
2026-07-24  2:51       ` Thiago Jung Bauermann
2026-07-21 21:47   ` Luis
2026-07-27 17:14     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 08/10] gdb/linux-tdep: migrate parse_smaps_data " Matthieu Longo
2026-07-09  6:41   ` Thiago Jung Bauermann
2026-07-14  8:49     ` Matthieu Longo
2026-07-24  2:52       ` Thiago Jung Bauermann
2026-07-21 21:49   ` Luis
2026-07-27 17:17     ` Matthieu Longo
2026-07-07 15:48 ` [PATCH v1 09/10] gdb/linux-tdep: parse ProtectionKey in /proc/PID/smaps Matthieu Longo
2026-07-09  6:42   ` Thiago Jung Bauermann
2026-07-14  9:12     ` Matthieu Longo
2026-07-14  9:29       ` Matthieu Longo
2026-07-24  2:58         ` Thiago Jung Bauermann
2026-07-24 10:27           ` Yury Khrustalev
2026-07-25  6:40             ` Thiago Jung Bauermann
2026-07-27  8:22               ` Yury Khrustalev
2026-07-29  1:10                 ` Thiago Jung Bauermann
2026-07-21 21:57   ` Luis
2026-07-27 17:54     ` Matthieu Longo
2026-07-07 15:49 ` [PATCH v1 10/10] gdb/linux: add helpers to read AT_HWCAP3 and AT_HWCAP4 Matthieu Longo
2026-07-09  6:44   ` Thiago Jung Bauermann
2026-07-21 21:58     ` Luis
2026-07-27 17:32       ` Matthieu Longo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=590655c1-abed-4a16-b8cc-762f1d8e6093@simark.ca \
    --to=simark@simark.ca \
    --cc=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=luis.machado.foss@gmail.com \
    --cc=luis.machado@amd.com \
    --cc=matthieu.longo@arm.com \
    --cc=pedro@palves.net \
    --cc=tom@tromey.com \
    --cc=yury.khrustalev@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox