diff mbox series

[4/7] trace-cmd,libtraceevent: Check for plugin duplication

Message ID 20200122150002.763233-5-tz.stoyanov@gmail.com (mailing list archive)
State New
Headers show
Series trace-cmd,libtraceevent: Rework of plugin options APIs | expand

Commit Message

Tzvetomir Stoyanov (VMware) Jan. 22, 2020, 2:59 p.m. UTC
When loading new plugin, check if plugin with the same
file name is already registered. If there is such plugin,
unload it and then load the new one.
In case of duplication, the last one wins.

Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com>
---
 lib/traceevent/event-plugin.c | 50 +++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/lib/traceevent/event-plugin.c b/lib/traceevent/event-plugin.c
index e53b09c..a33cf09 100644
--- a/lib/traceevent/event-plugin.c
+++ b/lib/traceevent/event-plugin.c
@@ -432,16 +432,60 @@  void tep_print_plugins(struct trace_seq *s,
 	}
 }
 
+
+static void unload_plugin(void *handle, struct tep_handle *tep)
+{
+	tep_plugin_unload_func func;
+
+	if (!handle)
+		return;
+	func = dlsym(handle, TEP_PLUGIN_UNLOADER_NAME);
+	if (func)
+		func(tep);
+	dlclose(handle);
+}
+
+static struct tep_plugin_list *
+detach_plugin(const char *name, struct tep_plugin_list **plist)
+{
+	struct tep_plugin_list *plugins = *plist;
+	struct tep_plugin_list *prev = NULL;
+	char *file;
+
+	while (plugins) {
+		file = strrchr(plugins->name, '/');
+		if (file)
+			file++;
+		else
+			file = plugins->name;
+		if (!strcmp(file, name)) {
+			if (prev)
+				prev->next = plugins->next;
+			else
+				*plist = plugins->next;
+			return plugins;
+		}
+		prev = plugins;
+		plugins = plugins->next;
+	}
+
+	return NULL;
+}
+
 static void
 load_plugin(struct tep_handle *tep, const char *path,
 	    const char *file, void *data)
 {
 	struct tep_plugin_list **plugin_list = data;
+	struct tep_plugin_list *old;
 	tep_plugin_load_func func;
 	struct tep_plugin_list *list;
 	char *plugin;
 	void *handle;
 	int ret;
+	old = detach_plugin(file, plugin_list);
+	if (old)
+		unload_plugin(old->handle, tep);
 
 	ret = asprintf(&plugin, "%s/%s", path, file);
 	if (ret < 0) {
@@ -652,16 +696,12 @@  void tep_free_plugin_paths(struct tep_handle *tep)
 void
 tep_unload_plugins(struct tep_plugin_list *plugin_list, struct tep_handle *tep)
 {
-	tep_plugin_unload_func func;
 	struct tep_plugin_list *list;
 
 	while (plugin_list) {
 		list = plugin_list;
+		unload_plugin(list->handle, tep);
 		plugin_list = list->next;
-		func = dlsym(list->handle, TEP_PLUGIN_UNLOADER_NAME);
-		if (func)
-			func(tep);
-		dlclose(list->handle);
 		free(list->name);
 		free(list);
 	}