[DTrace-devel] [PATCH v2 05/19] Split dt_pid_create_probes() into pid and USDT functions
eugene.loh at oracle.com
eugene.loh at oracle.com
Tue Sep 24 20:25:49 UTC 2024
From: Eugene Loh <eugene.loh at oracle.com>
The function dt_pid_create_probes() creates both pid and usdt probes.
Once the dtrace session has started, however, we only need to watch
for new usdt probes.
Therefore, reorganize dt_pid_create_probes():
*) Rename
dt_pid_create_pid_probes()
to
dt_pid_create_pid_probes_proc()
and rename
dt_pid_create_usdt_probes()
to
dt_pid_create_usdt_probes_proc()
since these functions create probes for a specified process.
*) Break dt_pid_create_probes() into two functions:
dt_pid_create_pid_probes()
dt_pid_create_usdt_probes()
*) Make dt_pid_create_usdt_probes() available in dt_pid.h.
Also, start building support for wildcard USDT pid specifications.
Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
libdtrace/dt_pid.c | 137 +++++++++++++++++++++++++++++++++------------
libdtrace/dt_pid.h | 2 +
2 files changed, 102 insertions(+), 37 deletions(-)
diff --git a/libdtrace/dt_pid.c b/libdtrace/dt_pid.c
index 996543b1f..62060b592 100644
--- a/libdtrace/dt_pid.c
+++ b/libdtrace/dt_pid.c
@@ -605,9 +605,12 @@ dt_pid_fix_mod(dt_pid_probe_t *pp, dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
return pmp;
}
+/*
+ * Create pid probes for the specified process.
+ */
static int
-dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
- dt_pcb_t *pcb, dt_proc_t *dpr)
+dt_pid_create_pid_probes_proc(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
+ dt_pcb_t *pcb, dt_proc_t *dpr)
{
dt_pid_probe_t pp;
int ret = 0;
@@ -702,6 +705,7 @@ dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
return ret;
}
+
/*
* Read a file into a buffer and return it.
*/
@@ -780,24 +784,21 @@ validate_dof_record(const char *path, const dof_parsed_t *parsed,
/*
* Create underlying probes relating to the probespec passed on input.
*
- * If dpr is set, just set up probes relating to mappings found in that one
- * process. (dpr must in this case be locked.)
+ * dpr must be set and locked. Just set up probes relating to mappings found
+ * in this one process.
*
* Return 0 on success or -1 on error. (Failure to create specific underlying
* probes is not an error.)
*/
static int
-dt_pid_create_usdt_probes(dtrace_hdl_t *dtp, dt_proc_t *dpr, dtrace_probedesc_t *pdp,
- dt_pcb_t *pcb)
+dt_pid_create_usdt_probes_proc(dtrace_hdl_t *dtp, dt_proc_t *dpr,
+ dtrace_probedesc_t *pdp, dt_pcb_t *pcb)
{
const dt_provider_t *pvp;
int ret = 0;
char *probepath = NULL;
glob_t probeglob = {0};
- /*
- * Systemwide probing: not yet implemented.
- */
assert(dpr != NULL && dpr->dpr_proc);
assert(MUTEX_HELD(&dpr->dpr_lock));
@@ -1094,64 +1095,126 @@ dt_pid_get_pid(const dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb,
return pid;
}
+/*
+ * Create pid probes. Return 0 on success (even if no probes are
+ * created, since there might still be USDT probes) and -1 on error.
+ */
int
-dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
+dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
{
+ pid_t pid;
char provname[DTRACE_PROVNAMELEN];
dt_proc_t *dpr;
- pid_t pid;
- int err = 0;
+ int err;
assert(pcb != NULL);
- if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
+ /* Exclude pid0 from being specifically requested. */
+ if (strcmp(pdp->prv, "pid0") == 0) {
+ dt_pid_error(dtp, pcb, NULL, D_PROC_BADPID,
+ "pid0 does not contain a valid pid");
return -1;
+ }
+ /* Extract the pid. */
+ pid = dt_pid_get_pid(pdp, dtp, pcb, NULL);
+ if (pid <= 0)
+ return 0;
+
+ /* Check whether pid$pid matches the probe description. */
snprintf(provname, sizeof(provname), "pid%d", (int)pid);
+ if (gmatch(provname, pdp->prv) == 0)
+ return 0;
- if (gmatch(provname, pdp->prv) != 0) {
- if (dt_proc_grab_lock(dtp, pid, DTRACE_PROC_WAITING) < 0) {
- dt_pid_error(dtp, pcb, NULL, D_PROC_GRAB,
- "failed to grab process %d", (int)pid);
- return -1;
- }
+ /* Grab the process. */
+ if (dt_proc_grab_lock(dtp, pid, DTRACE_PROC_WAITING) < 0) {
+ dt_pid_error(dtp, pcb, NULL, D_PROC_GRAB,
+ "failed to grab process %d", (int)pid);
+ return -1;
+ }
+ dpr = dt_proc_lookup(dtp, pid);
+ assert(dpr != NULL);
- dpr = dt_proc_lookup(dtp, pid);
- assert(dpr != NULL);
+ /* Create the pid probes for this process. */
+ err = dt_pid_create_pid_probes_proc(pdp, dtp, pcb, dpr);
+ dt_proc_release_unlock(dtp, pid);
- err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr);
- dt_proc_release_unlock(dtp, pid);
+ return err;
+}
+
+int
+dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
+{
+ glob_t globbuf;
+ char *globpat = NULL;
+ int err = 0, i, nmatches = 0;
+
+ assert(pcb != NULL);
+
+ /* If it's strictly a pid provider, we're done. */
+ if (strncmp(pdp->prv, "pid", 3) == 0 && isdigit(pdp->prv[3])) {
+ const char *p = &pdp->prv[4];
+
+ while (isdigit(*p))
+ p++;
+ if (*p == '\0')
+ return 0;
}
- /*
- * If it's not strictly a pid provider, we might match a USDT provider.
- */
- if (strcmp(provname, pdp->prv) != 0) {
+ /* Look for USDT probes. */
+ asprintf(&globpat, "%s/probes/*/%s", dtp->dt_dofstash_path, pdp->prv[0] ? pdp->prv : "*");
+ nmatches = glob(globpat, 0, NULL, &globbuf) ? 0 : globbuf.gl_pathc;
+ for (i = 0; i < nmatches; i++) {
+ char *s = globbuf.gl_pathv[i]
+ + strlen(dtp->dt_dofstash_path)
+ + strlen("/probes/");
+ pid_t pid;
+ dt_proc_t *dpr;
+ dtrace_probedesc_t pdptmp;
+
+ /* Pull out the pid. */
+ pid = atoll(s);
+
+ /* Check, since dtprobed takes a while to clean up dead processes. */
+ if (!Pexists(pid))
+ continue;
+
+ /* Grab the process. */
if (dt_proc_grab_lock(dtp, pid, DTRACE_PROC_WAITING |
DTRACE_PROC_SHORTLIVED) < 0) {
dt_pid_error(dtp, pcb, NULL, D_PROC_GRAB,
"failed to grab process %d", (int)pid);
return -1;
}
-
dpr = dt_proc_lookup(dtp, pid);
assert(dpr != NULL);
- err = dt_pid_create_usdt_probes(dtp, dpr, pdp, pcb);
+ /* Create USDT probes for this process. */
+ pdptmp.prv = strchr(s, '/') + 1;
+ pdptmp.mod = pdp->mod[0] == '\0' ? "*" : pdp->mod;
+ pdptmp.fun = pdp->fun[0] == '\0' ? "*" : pdp->fun;
+ pdptmp.prb = pdp->prb[0] == '\0' ? "*" : pdp->prb;
+ if (dt_pid_create_usdt_probes_proc(dtp, dpr, &pdptmp, pcb))
+ err = 1;
- /*
- * Put the module name in its canonical form.
- */
- dt_pid_fix_mod(NULL, pdp, dtp, dpr->dpr_pid);
+ dt_pid_fix_mod(NULL, &pdptmp, dtp, dpr->dpr_pid);
dt_proc_release_unlock(dtp, pid);
}
-
- /* (USDT systemwide probing goes here.) */
+ free(globpat);
+ globfree(&globbuf);
return err ? -1 : 0;
}
+int
+dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
+{
+ if (dt_pid_create_pid_probes(pdp, dtp, pcb))
+ return -1;
+ return dt_pid_create_usdt_probes(pdp, dtp, pcb);
+}
+
int
dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
{
@@ -1179,7 +1242,7 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
pd.fun = strdup(pd.fun); /* we may change it */
if (gmatch(provname, pdp->prv) != 0 &&
- dt_pid_create_pid_probes(&pd, dtp, NULL, dpr) != 0)
+ dt_pid_create_pid_probes_proc(&pd, dtp, NULL, dpr) != 0)
ret = 1;
/*
@@ -1187,7 +1250,7 @@ dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
* a USDT provider.
*/
if (strcmp(provname, pdp->prv) != 0) {
- if (dt_pid_create_usdt_probes(dtp, dpr, pdp, NULL) < 0)
+ if (dt_pid_create_usdt_probes_proc(dtp, dpr, pdp, NULL) < 0)
ret = 1;
else
dt_pid_fix_mod(NULL, pdp, dtp, dpr->dpr_pid);
diff --git a/libdtrace/dt_pid.h b/libdtrace/dt_pid.h
index 497c77510..9277c6bc0 100644
--- a/libdtrace/dt_pid.h
+++ b/libdtrace/dt_pid.h
@@ -16,6 +16,8 @@
extern "C" {
#endif
+extern int dt_pid_create_usdt_probes(dtrace_probedesc_t *, dtrace_hdl_t *,
+ dt_pcb_t *);
extern int dt_pid_create_probes(dtrace_probedesc_t *, dtrace_hdl_t *,
dt_pcb_t *);
extern int dt_pid_create_probes_module(dtrace_hdl_t *, dt_proc_t *);
--
2.43.5
More information about the DTrace-devel
mailing list