static gboolean _gst_initialization_failure = FALSE;
extern gint _gst_trace_on;
+/* set to TRUE when segfaults need to be left as is */
+gboolean _gst_enable_segfault = FALSE;
+
extern GThreadFunctions gst_thread_dummy_functions;
ARG_PLUGIN_SPEW,
ARG_PLUGIN_PATH,
ARG_PLUGIN_LOAD,
+ ARG_SEGFAULT_ENABLE,
ARG_SCHEDULER,
ARG_REGISTRY
};
{"gst-plugin-spew", NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_SPEW, N_("enable verbose plugin loading diagnostics"), NULL},
{"gst-plugin-path", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_PATH, N_("'" G_SEARCHPATH_SEPARATOR_S "'--separated path list for loading plugins"), "PATHS"},
{"gst-plugin-load", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_PLUGIN_LOAD, N_("comma-separated list of plugins to preload in addition to the list stored in env variable GST_PLUGIN_PATH"), "PLUGINS"},
+ {"gst-enable-segfault",NUL, POPT_ARG_NONE|POPT_ARGFLAG_STRIP, NULL, ARG_SEGFAULT_ENABLE,N_("enable receiving of segmentation faults during plugin loading"), NULL},
{"gst-scheduler", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_SCHEDULER, N_("scheduler to use ('"GST_SCHEDULER_DEFAULT_NAME"' is the default)"), "SCHEDULER"},
{"gst-registry", NUL, POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, ARG_REGISTRY, N_("registry to use") , "REGISTRY"},
POPT_TABLEEND
case ARG_PLUGIN_LOAD:
split_and_iterate (arg, ",", prepare_for_load_plugin_func, NULL);
break;
+ case ARG_SEGFAULT_ENABLE:
+ _gst_enable_segfault = TRUE;
+ break;
case ARG_SCHEDULER:
gst_scheduler_factory_set_default_name (arg);
break;
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
+#include <signal.h>
#include "gst_private.h"
static GModule *main_module = NULL;
static GList *_gst_plugin_static = NULL;
+/* static variables for segfault handling of plugin loading */
+static char *_gst_plugin_fault_handler_filename = NULL;
+extern gboolean *_gst_enable_segfault; /* see gst.c */
+static gboolean *_gst_plugin_fault_handler_is_setup = FALSE;
+
/* list of valid licenses.
* One of these must be specified or the plugin won't be loaded
* Contact gstreamer-devel@lists.sourceforge.net if your license should be
}
/**
+ * _gst_plugin_fault_handler_restore:
+ * segfault handler restorer
+ */
+static void
+_gst_plugin_fault_handler_restore (void)
+{
+ struct sigaction action;
+
+ memset (&action, 0, sizeof (action));
+ action.sa_handler = SIG_DFL;
+
+ sigaction (SIGSEGV, &action, NULL);
+}
+
+/**
+ * _gst_plugin_fault_handler_sighandler:
+ * segfault handler implementation
+ */
+static void
+_gst_plugin_fault_handler_sighandler (int signum)
+{
+ /* We need to restore the fault handler or we'll keep getting it */
+ _gst_plugin_fault_handler_restore ();
+
+ switch (signum)
+ {
+ case SIGSEGV:
+ g_print ("\nERROR:");
+ g_print ("Caught a segmentation fault while loading plugin file:\n");
+ g_print ("%s\n\n", _gst_plugin_fault_handler_filename);
+ g_print ("Please either:\n");
+ g_print ("- remove it and restart.\n");
+ g_print ("- run with --gst-enable-segfault and debug.\n");
+ exit (-1);
+ break;
+ default:
+ g_print ("Caught unhandled signal on plugin loading\n");
+ break;
+ }
+}
+
+/**
+ * _gst_plugin_fault_handler_setup:
+ * sets up the segfault handler
+ */
+static void
+_gst_plugin_fault_handler_setup (void)
+{
+ struct sigaction action;
+
+ /* if asked to leave segfaults alone, just return */
+ if (_gst_enable_segfault) return;
+
+ if (_gst_plugin_fault_handler_is_setup) return;
+
+ memset (&action, 0, sizeof (action));
+ action.sa_handler = _gst_plugin_fault_handler_sighandler;
+
+ sigaction (SIGSEGV, &action, NULL);
+}
+
+static void
+_gst_plugin_fault_handler_setup ();
+
+/**
* gst_plugin_load_file:
* @plugin: The plugin to load
* @error: Pointer to a NULL-valued GError.
*
* Load the given plugin.
*
- * Returns: a new GstPlugin or NULL, if an error occured
+ * Returns: a new GstPlugin or NULL, if an error occurred.
*/
GstPlugin *
gst_plugin_load_file (const gchar *filename, GError **error)
GST_PLUGIN_ERROR,
GST_PLUGIN_ERROR_MODULE,
"Problem opening file %s\n",
- filename);
- return FALSE;
+ filename);
+ return NULL;
}
module = g_module_open (filename, G_MODULE_BIND_LAZY);
desc->name);
}
+ /* this is where we load the actual .so, so let's trap SIGSEGV */
+ _gst_plugin_fault_handler_setup ();
+ _gst_plugin_fault_handler_filename = plugin->filename;
+
if (gst_plugin_register_func (plugin, module, desc)) {
+ /* remove signal handler */
+ _gst_plugin_fault_handler_restore ();
+ _gst_plugin_fault_handler_filename = NULL;
GST_INFO ("plugin \"%s\" loaded", plugin->filename);
return plugin;
} else {
+ /* remove signal handler */
+ _gst_plugin_fault_handler_restore ();
GST_DEBUG ("gst_plugin_register_func failed for plugin \"%s\"", filename);
/* plugin == NULL */
g_set_error (error,