[gnome-builder/wip/gtk4-port] plugins/valgrind: port to C



commit 4569090d87b57e957652ccb866609c664622fb54
Author: Christian Hergert <chergert redhat com>
Date:   Tue Apr 19 13:15:38 2022 -0700

    plugins/valgrind: port to C
    
    As much as I want to enable plugins in Python, some of them are just
    easier to debug from C, paricularly when lifecycle management is occuring
    during teardown of the foundry.

 .../valgrind/gbp-valgrind-workbench-addin.c        | 266 +++++++++++++++++++++
 .../valgrind/gbp-valgrind-workbench-addin.h        |  31 +++
 src/plugins/valgrind/meson.build                   |  23 +-
 src/plugins/valgrind/valgrind-plugin.c             |  37 +++
 src/plugins/valgrind/valgrind.plugin               |   8 +-
 src/plugins/valgrind/valgrind_plugin.py            |  89 -------
 6 files changed, 346 insertions(+), 108 deletions(-)
---
diff --git a/src/plugins/valgrind/gbp-valgrind-workbench-addin.c 
b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
new file mode 100644
index 000000000..6bc9ad614
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
@@ -0,0 +1,266 @@
+/* gbp-valgrind-workbench-addin.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-valgrind-workbench-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libide-foundry.h>
+#include <libide-gui.h>
+
+#include "gbp-valgrind-workbench-addin.h"
+
+struct _GbpValgrindWorkbenchAddin
+{
+  GObject          parent_instance;
+
+  IdeWorkbench    *workbench;
+  IdeRunManager   *run_manager;
+  IdeBuildManager *build_manager;
+  char            *log_name;
+
+  guint            has_handler : 1;
+};
+
+static void
+gbp_valgrind_workbench_addin_runner_exited_cb (GbpValgrindWorkbenchAddin *self,
+                                               IdeRunner                 *runner)
+{
+  g_autoptr(GFile) file = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_RUNNER (runner));
+
+  if (self->workbench == NULL || self->log_name == NULL)
+    IDE_EXIT;
+
+  file = g_file_new_for_path (self->log_name);
+  ide_workbench_open_async (self->workbench,
+                            file,
+                            "editorui",
+                            IDE_BUFFER_OPEN_FLAGS_NONE,
+                            NULL, NULL, NULL, NULL);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_workbench_addin_run_handler (IdeRunManager *run_manager,
+                                          IdeRunner     *runner,
+                                          gpointer       user_data)
+{
+  GbpValgrindWorkbenchAddin *self = user_data;
+  g_autoptr(GError) error = NULL;
+  g_autofree char *name = NULL;
+  char log_fd_param[32];
+  int map_fd;
+  int fd;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_RUN_MANAGER (run_manager));
+  g_assert (IDE_IS_RUNNER (runner));
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+
+  /* Create a temp file to write to and an FD to access it */
+  errno = 0;
+  fd = g_file_open_tmp ("gnome-builder-valgrind-XXXXXX.txt", &name, &error);
+  if (fd < 0)
+    {
+      g_warning ("Failed to create FD to communicate with Valgrind: %s: %s",
+                 g_strerror (errno), error->message);
+      IDE_EXIT;
+    }
+
+  /* Save the filename so we can open it after exiting */
+  g_clear_pointer (&self->log_name, g_free);
+  self->log_name = g_steal_pointer (&name);
+
+  /* Get the FD number as it will exist within the subprocess */
+  map_fd = ide_runner_take_fd (runner, fd, -1);
+  g_snprintf (log_fd_param, sizeof log_fd_param, "--log-fd=%d", map_fd);
+
+  /* Setup arguments to valgrind so it writes output to temp file. Add in
+   * reverse order so we can just use prepend() repeatedly */
+  ide_runner_prepend_argv (runner, "--track-origins=yes");
+  ide_runner_prepend_argv (runner, log_fd_param);
+  ide_runner_prepend_argv (runner, "valgrind");
+
+  g_signal_connect_object (runner,
+                           "exited",
+                           G_CALLBACK (gbp_valgrind_workbench_addin_runner_exited_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_workbench_addin_notify_pipeline_cb (GbpValgrindWorkbenchAddin *self,
+                                                 GParamSpec                *pspec,
+                                                 IdeBuildManager           *build_manager)
+{
+  IdePipeline *pipeline;
+  IdeRuntime *runtime;
+  gboolean can_handle = FALSE;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_BUILD_MANAGER (build_manager));
+  g_assert (IDE_IS_RUN_MANAGER (self->run_manager));
+
+  if (!(pipeline = ide_build_manager_get_pipeline (build_manager)) ||
+      !(runtime = ide_pipeline_get_runtime (pipeline)) ||
+      !ide_runtime_contains_program_in_path (runtime, "valgrind", NULL))
+    IDE_GOTO (not_found);
+
+  can_handle = TRUE;
+
+not_found:
+  if (can_handle != self->has_handler)
+    {
+      self->has_handler = can_handle;
+
+      if (can_handle)
+        ide_run_manager_add_handler (self->run_manager,
+                                     "valgrind",
+                                     _("Run with Valgrind"),
+                                     "system-run-symbolic",
+                                     "<Primary>F10",
+                                     gbp_valgrind_workbench_addin_run_handler,
+                                     g_object_ref (self),
+                                     g_object_unref);
+      else
+        ide_run_manager_remove_handler (self->run_manager, "valgrind");
+    }
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_workbench_addin_project_loaded (IdeWorkbenchAddin *addin,
+                                             IdeProjectInfo    *project_info)
+{
+  GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
+  IdeBuildManager *build_manager;
+  IdeRunManager *run_manager;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_PROJECT_INFO (project_info));
+  g_assert (IDE_IS_WORKBENCH (self->workbench));
+
+  context = ide_workbench_get_context (self->workbench);
+  build_manager = ide_build_manager_from_context (context);
+  run_manager = ide_run_manager_from_context (context);
+
+  g_set_object (&self->build_manager, build_manager);
+  g_set_object (&self->run_manager, run_manager);
+
+  g_signal_connect_object (build_manager,
+                           "notify::pipeline",
+                           G_CALLBACK (gbp_valgrind_workbench_addin_notify_pipeline_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  gbp_valgrind_workbench_addin_notify_pipeline_cb (self, NULL, build_manager);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_workbench_addin_load (IdeWorkbenchAddin *addin,
+                                   IdeWorkbench      *workbench)
+{
+  GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_WORKBENCH (workbench));
+
+  self->workbench = workbench;
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_workbench_addin_unload (IdeWorkbenchAddin *addin,
+                                     IdeWorkbench      *workbench)
+{
+  GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
+  g_assert (IDE_IS_WORKBENCH (workbench));
+
+  if (self->build_manager != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (self->build_manager,
+                                            G_CALLBACK (gbp_valgrind_workbench_addin_notify_pipeline_cb),
+                                            self);
+      g_clear_object (&self->build_manager);
+    }
+
+  if (self->run_manager != NULL)
+    {
+      if (self->has_handler)
+        ide_run_manager_remove_handler (self->run_manager, "valgrind");
+      g_clear_object (&self->run_manager);
+    }
+
+  g_clear_pointer (&self->log_name, g_free);
+
+  self->workbench = NULL;
+
+  IDE_EXIT;
+}
+
+static void
+workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
+{
+  iface->load = gbp_valgrind_workbench_addin_load;
+  iface->unload = gbp_valgrind_workbench_addin_unload;
+  iface->project_loaded = gbp_valgrind_workbench_addin_project_loaded;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpValgrindWorkbenchAddin, gbp_valgrind_workbench_addin, G_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
+
+static void
+gbp_valgrind_workbench_addin_class_init (GbpValgrindWorkbenchAddinClass *klass)
+{
+}
+
+static void
+gbp_valgrind_workbench_addin_init (GbpValgrindWorkbenchAddin *self)
+{
+}
diff --git a/src/plugins/valgrind/gbp-valgrind-workbench-addin.h 
b/src/plugins/valgrind/gbp-valgrind-workbench-addin.h
new file mode 100644
index 000000000..448f02ec8
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-workbench-addin.h
@@ -0,0 +1,31 @@
+/* gbp-valgrind-workbench-addin.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VALGRIND_WORKBENCH_ADDIN (gbp_valgrind_workbench_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpValgrindWorkbenchAddin, gbp_valgrind_workbench_addin, GBP, 
VALGRIND_WORKBENCH_ADDIN, GObject)
+
+G_END_DECLS
diff --git a/src/plugins/valgrind/meson.build b/src/plugins/valgrind/meson.build
index 240671f1f..72bb792f9 100644
--- a/src/plugins/valgrind/meson.build
+++ b/src/plugins/valgrind/meson.build
@@ -1,21 +1,16 @@
 if get_option('plugin_valgrind')
 
-valgrind_resources = gnome.compile_resources(
-  'valgrind_plugin',
+plugins_sources += files([
+  'valgrind-plugin.c',
+  'gbp-valgrind-workbench-addin.c',
+])
+
+plugin_valgrind_resources = gnome.compile_resources(
+  'valgrind-resources',
   'valgrind.gresource.xml',
-  gresource_bundle: true,
-           install: true,
-       install_dir: plugindir,
+  c_name: 'gbp_valgrind',
 )
 
-install_data('valgrind_plugin.py', install_dir: plugindir)
-
-configure_file(
-          input: 'valgrind.plugin',
-         output: 'valgrind.plugin',
-  configuration: config_h,
-        install: true,
-    install_dir: plugindir,
-)
+plugins_sources += plugin_valgrind_resources
 
 endif
diff --git a/src/plugins/valgrind/valgrind-plugin.c b/src/plugins/valgrind/valgrind-plugin.c
new file mode 100644
index 000000000..d6d0a5715
--- /dev/null
+++ b/src/plugins/valgrind/valgrind-plugin.c
@@ -0,0 +1,37 @@
+/* valgrind-plugin.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "valgrind-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-gui.h>
+
+#include "gbp-valgrind-workbench-addin.h"
+
+_IDE_EXTERN void
+_gbp_valgrind_register_types (PeasObjectModule *module)
+{
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_WORKBENCH_ADDIN,
+                                              GBP_TYPE_VALGRIND_WORKBENCH_ADDIN);
+}
diff --git a/src/plugins/valgrind/valgrind.plugin b/src/plugins/valgrind/valgrind.plugin
index c2c47b91b..028e7c046 100644
--- a/src/plugins/valgrind/valgrind.plugin
+++ b/src/plugins/valgrind/valgrind.plugin
@@ -1,11 +1,9 @@
 [Plugin]
 Authors=Christian Hergert <christian hergert me>
 Builtin=true
-Copyright=Copyright © 2017-2018 Christian Hergert
+Copyright=Copyright © 2017-2022 Christian Hergert
 Description=Provides integration with valgrind
-Loader=python3
-Module=valgrind_plugin
+Embedded=_gbp_valgrind_register_types
+Module=valgrind
 Name=Valgrind
-X-Builder-ABI=@PACKAGE_ABI@
-X-Has-Resources=true
 X-Category=debuggers


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]