[v5,09/12] libdwfl_stacktrace [9/12]: add dwflst_tracker_find_pid
Commit Message
Changes for v4:
- Separate out libdwfl_stacktrace, as requested.
Changes for v2:
- Add locking for dwfltab.
* * *
New function that retrieves the Dwfl for a particular PID, or,
if the Dwfl is absent, creates it via a provided callback
and adds it to the table later, when the PID is confirmed
via dwfl_attach_state.
* libdwfl_stacktrace/libdwfl_stacktrace.h (dwflst_tracker_find_pid):
New function.
* libdwfl_stacktrace/dwfl_process_tracker.c (dwflst_tracker_find_pid):
New function; find a Dwfl in the dwfltab or create one using the
provided callback. The newly created Dwfl will be added to the
dwfltab automatically when its pid is confirmed by a call to
dwfl_attach_state.
* libdw/libdw.map: Add dwflst_tracker_find_pid.
---
libdw/libdw.map | 1 +
libdwfl_stacktrace/dwflst_process_tracker.c | 26 +++++++++++++++++++++
libdwfl_stacktrace/libdwfl_stacktrace.h | 11 +++++++++
3 files changed, 38 insertions(+)
Comments
On Thu, Apr 24, 2025 at 5:49 PM Serhei Makarov <serhei@serhei.io> wrote:
>
> Changes for v4:
>
> - Separate out libdwfl_stacktrace, as requested.
>
> Changes for v2:
>
> - Add locking for dwfltab.
>
> * * *
>
> New function that retrieves the Dwfl for a particular PID, or,
> if the Dwfl is absent, creates it via a provided callback
> and adds it to the table later, when the PID is confirmed
> via dwfl_attach_state.
>
> * libdwfl_stacktrace/libdwfl_stacktrace.h (dwflst_tracker_find_pid):
> New function.
> * libdwfl_stacktrace/dwfl_process_tracker.c (dwflst_tracker_find_pid):
> New function; find a Dwfl in the dwfltab or create one using the
> provided callback. The newly created Dwfl will be added to the
> dwfltab automatically when its pid is confirmed by a call to
> dwfl_attach_state.
> * libdw/libdw.map: Add dwflst_tracker_find_pid.
> ---
> libdw/libdw.map | 1 +
> libdwfl_stacktrace/dwflst_process_tracker.c | 26 +++++++++++++++++++++
> libdwfl_stacktrace/libdwfl_stacktrace.h | 11 +++++++++
> 3 files changed, 38 insertions(+)
>
> diff --git a/libdw/libdw.map b/libdw/libdw.map
> index 46d0878a..688e415c 100644
> --- a/libdw/libdw.map
> +++ b/libdw/libdw.map
> @@ -404,4 +404,5 @@ ELFUTILS_0.193_EXPERIMENTAL {
> dwflst_tracker_cache_elf;
> dwflst_module_gettracker;
> dwflst_tracker_linux_proc_find_elf;
> + dwflst_tracker_find_pid;
> };
> diff --git a/libdwfl_stacktrace/dwflst_process_tracker.c b/libdwfl_stacktrace/dwflst_process_tracker.c
> index f72b72b0..fc019b23 100644
> --- a/libdwfl_stacktrace/dwflst_process_tracker.c
> +++ b/libdwfl_stacktrace/dwflst_process_tracker.c
> @@ -67,6 +67,32 @@ Dwfl *dwflst_tracker_dwfl_begin (Dwflst_Process_Tracker *tracker)
> return dwfl;
> }
>
> +Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
> + pid_t pid,
> + Dwfl *(*callback) (Dwflst_Process_Tracker *,
> + pid_t, void *),
> + void *arg)
> +{
> + Dwfl *dwfl = NULL;
> +
> + rwlock_rdlock (tracker->dwfltab_lock);
> + dwflst_tracker_dwfl_info *ent
> + = dwflst_tracker_dwfltab_find(&tracker->dwfltab, pid);
> + rwlock_unlock (tracker->dwfltab_lock);
> +
> + if (ent != NULL && !ent->invalid)
> + dwfl = ent->dwfl;
> + if (dwfl == NULL && callback != NULL)
> + dwfl = callback(tracker, pid, arg);
> + if (dwfl != NULL)
> + {
> + assert (dwfl->tracker == tracker);
> + /* XXX: dwfl added to dwfltab when dwfl->process set in dwfl_attach_state.
> + Prior to that, the pid is not confirmed. */
Should this information be incorporated into the libdw_stacktrace.h
doc comment for dwflst_process_tracker?
> + }
> +
> + return dwfl;
> +}
>
> void
> internal_function
> diff --git a/libdwfl_stacktrace/libdwfl_stacktrace.h b/libdwfl_stacktrace/libdwfl_stacktrace.h
> index d29dc640..ed6a6a5c 100644
> --- a/libdwfl_stacktrace/libdwfl_stacktrace.h
> +++ b/libdwfl_stacktrace/libdwfl_stacktrace.h
> @@ -79,6 +79,17 @@ extern bool dwflst_tracker_cache_elf (Dwflst_Process_Tracker *tracker,
> Elf *elf, int fd)
> __nonnull_attribute__ (1, 2);
>
> +/* Find the Dwfl corresponding to PID. If CALLBACK is non-NULL and
> + the Dwfl has not been created, invoke CALLBACK to create the Dwfl
> + and then store it in the tracker. */
I would mention what a return value of NULL means (ex. callback failed).
> +extern Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
> + pid_t pid,
> + Dwfl *(*callback) (Dwflst_Process_Tracker *tracker,
> + pid_t pid,
> + void *arg),
> + void *arg)
> + __nonnull_attribute__ (1);
> +
> /* For implementing a find_elf callback based on the prior two functions.
> Returns the Dwflst_Process_Tracker corresponding to MOD. */
> extern Dwflst_Process_Tracker *dwflst_module_gettracker (Dwfl_Module *mod);
> --
> 2.47.0
>
Aaron
@@ -404,4 +404,5 @@ ELFUTILS_0.193_EXPERIMENTAL {
dwflst_tracker_cache_elf;
dwflst_module_gettracker;
dwflst_tracker_linux_proc_find_elf;
+ dwflst_tracker_find_pid;
};
@@ -67,6 +67,32 @@ Dwfl *dwflst_tracker_dwfl_begin (Dwflst_Process_Tracker *tracker)
return dwfl;
}
+Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
+ pid_t pid,
+ Dwfl *(*callback) (Dwflst_Process_Tracker *,
+ pid_t, void *),
+ void *arg)
+{
+ Dwfl *dwfl = NULL;
+
+ rwlock_rdlock (tracker->dwfltab_lock);
+ dwflst_tracker_dwfl_info *ent
+ = dwflst_tracker_dwfltab_find(&tracker->dwfltab, pid);
+ rwlock_unlock (tracker->dwfltab_lock);
+
+ if (ent != NULL && !ent->invalid)
+ dwfl = ent->dwfl;
+ if (dwfl == NULL && callback != NULL)
+ dwfl = callback(tracker, pid, arg);
+ if (dwfl != NULL)
+ {
+ assert (dwfl->tracker == tracker);
+ /* XXX: dwfl added to dwfltab when dwfl->process set in dwfl_attach_state.
+ Prior to that, the pid is not confirmed. */
+ }
+
+ return dwfl;
+}
void
internal_function
@@ -79,6 +79,17 @@ extern bool dwflst_tracker_cache_elf (Dwflst_Process_Tracker *tracker,
Elf *elf, int fd)
__nonnull_attribute__ (1, 2);
+/* Find the Dwfl corresponding to PID. If CALLBACK is non-NULL and
+ the Dwfl has not been created, invoke CALLBACK to create the Dwfl
+ and then store it in the tracker. */
+extern Dwfl *dwflst_tracker_find_pid (Dwflst_Process_Tracker *tracker,
+ pid_t pid,
+ Dwfl *(*callback) (Dwflst_Process_Tracker *tracker,
+ pid_t pid,
+ void *arg),
+ void *arg)
+ __nonnull_attribute__ (1);
+
/* For implementing a find_elf callback based on the prior two functions.
Returns the Dwflst_Process_Tracker corresponding to MOD. */
extern Dwflst_Process_Tracker *dwflst_module_gettracker (Dwfl_Module *mod);