[DTrace-devel] [PATCH 25/47] Implement probe cleanup function support for providers

Kris Van Hees kris.van.hees at oracle.com
Sun May 3 20:17:38 PDT 2020


Some providers need to be able to do some custom cleanup when a probe
is being destroyed.  This patch adds a callback function to the provider
implementation.  The probe_fini callback will be called for every probe
that belongs to a provider that implements such a callback.

This patch moves the destoying of providers to occur after probes have
been destroyed.  It also changes the allocation of probes to enforce that
the allocated memory is initialized with zeros.  It guards against the
dt_probe_destroy() function being called for dynamically created probes
that are (so far) not linked into the hash tables.

As a little bonus, this patch also fixes one of the argument names in
the prototype of the probe_info callback.

Orabug: 31220519
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees at oracle.com>
Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_open.c     |  7 ++++---
 libdtrace/dt_probe.c    | 43 +++++++++++++++++++++++++++++++++++++----
 libdtrace/dt_probe.h    |  1 +
 libdtrace/dt_provider.h |  4 +++-
 4 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index e8c78492..0209840f 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1182,9 +1182,6 @@ dtrace_close(dtrace_hdl_t *dtp)
 	if (dtp->dt_ctfa != NULL)
 		ctf_arc_close(dtp->dt_ctfa);
 
-	while ((pvp = dt_list_next(&dtp->dt_provlist)) != NULL)
-		dt_provider_destroy(dtp, pvp);
-
 	dt_pcap_destroy(dtp);
 
 	if (dtp->dt_cdefs_fd != -1)
@@ -1204,6 +1201,10 @@ dtrace_close(dtrace_hdl_t *dtp)
 	dt_pebs_exit(dtp);
 	dt_pfdict_destroy(dtp);
 	dt_dof_fini(dtp);
+	dt_probe_fini(dtp);
+
+	while ((pvp = dt_list_next(&dtp->dt_provlist)) != NULL)
+		dt_provider_destroy(dtp, pvp);
 
 	for (i = 1; i < dtp->dt_cpp_argc; i++)
 		free(dtp->dt_cpp_argv[i]);
diff --git a/libdtrace/dt_probe.c b/libdtrace/dt_probe.c
index ee344881..823f0dd2 100644
--- a/libdtrace/dt_probe.c
+++ b/libdtrace/dt_probe.c
@@ -414,8 +414,9 @@ dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc,
 		xargc = nargc;
 	}
 
-	if ((prp = dt_alloc(dtp, sizeof (dt_probe_t))) == NULL)
-		return (NULL);
+	prp = dt_zalloc(dtp, sizeof(dt_probe_t));
+	if (prp == NULL)
+		return NULL;
 
 	prp->prov = NULL;
 	prp->pr_ident = idp;
@@ -440,7 +441,7 @@ dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc,
 	    (prp->xargc != 0 && prp->mapping == NULL) ||
 	    (prp->argc != 0 && prp->argv == NULL)) {
 		dt_probe_destroy(prp);
-		return (NULL);
+		return NULL;
 	}
 
 	for (i = 0; i < xargc; i++, xargs = xargs->dn_list) {
@@ -465,7 +466,8 @@ dt_probe_create(dtrace_hdl_t *dtp, dt_ident_t *idp, int protoc,
 		prp->nargv[i] = nargs;
 
 	idp->di_data = prp;
-	return (prp);
+
+	return prp;
 }
 
 void
@@ -493,6 +495,17 @@ dt_probe_destroy(dt_probe_t *prp)
 	else
 		dtp = yypcb->pcb_hdl;
 
+	if (prp->desc) {
+		dt_htab_delete(dtp->dt_byprv, prp);
+		dt_htab_delete(dtp->dt_bymod, prp);
+		dt_htab_delete(dtp->dt_byfun, prp);
+		dt_htab_delete(dtp->dt_byprb, prp);
+		dt_htab_delete(dtp->dt_byfqn, prp);
+	}
+
+	if (prp->prov && prp->prov->impl && prp->prov->impl->probe_fini)
+		prp->prov->impl->probe_fini(dtp, prp);
+
 	dt_node_list_free(&prp->nargs);
 	dt_node_list_free(&prp->xargs);
 
@@ -508,6 +521,13 @@ dt_probe_destroy(dt_probe_t *prp)
 
 	dt_free(dtp, prp->mapping);
 	dt_free(dtp, prp->argv);
+	if (prp->desc) {
+		dt_free(dtp, (void *)prp->desc->prv);
+		dt_free(dtp, (void *)prp->desc->mod);
+		dt_free(dtp, (void *)prp->desc->fun);
+		dt_free(dtp, (void *)prp->desc->prb);
+		dt_free(dtp, (void *)prp->desc);
+	}
 	dt_free(dtp, prp);
 }
 
@@ -1250,6 +1270,21 @@ dt_probe_init(dtrace_hdl_t *dtp)
 	dtp->dt_probe_id = 1;
 }
 
+void
+dt_probe_fini(dtrace_hdl_t *dtp)
+{
+	uint32_t	i;
+
+	for (i = 0; i < dtp->dt_probes_sz; i++) {
+		dt_probe_t	*prp = dtp->dt_probes[i];
+
+		if (prp == NULL)
+			continue;
+
+		dt_probe_destroy(prp);
+	}
+}
+
 void
 dt_probe_stats(dtrace_hdl_t *dtp)
 {
diff --git a/libdtrace/dt_probe.h b/libdtrace/dt_probe.h
index 5814836b..7feeeff2 100644
--- a/libdtrace/dt_probe.h
+++ b/libdtrace/dt_probe.h
@@ -82,6 +82,7 @@ extern int dt_probe_iter(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
 			 dt_probe_f *pfunc, dtrace_probe_f *dfunc, void *arg);
 
 extern void dt_probe_init(dtrace_hdl_t *dtp);
+extern void dt_probe_fini(dtrace_hdl_t *dtp);
 extern void dt_probe_stats(dtrace_hdl_t *dtp);
 
 #ifdef	__cplusplus
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index c2bc730a..165852cb 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -50,10 +50,12 @@ typedef struct dt_provimpl {
 	int prog_type;				/* BPF program type */
 	int (*populate)(dtrace_hdl_t *dtp);	/* register probes */
 	int (*probe_info)(dtrace_hdl_t *dtp,	/* get probe info */
-			  const struct dt_probe *prb,
+			  const struct dt_probe *prp,
 			  int *idp, int *argcp, dt_argdesc_t **argvp);
 	void (*trampoline)(dt_pcb_t *pcb,	/* generate BPF trampoline */
 			   int haspred);
+	int (*probe_fini)(dtrace_hdl_t *dtp,	/* probe cleanup */
+			  struct dt_probe *prb);
 } dt_provimpl_t;
 
 extern int tp_event_info(dtrace_hdl_t *dtp, FILE *f, int skip, int *idp,
-- 
2.26.0




More information about the DTrace-devel mailing list