implementing segfault handler for plugin loading

Original commit message from CVS:
implementing segfault handler for plugin loading
This commit is contained in:
Thomas Vander Stichele 2003-12-15 12:44:35 +00:00
parent 7943699850
commit a4f74f5eb4
3 changed files with 100 additions and 3 deletions

View file

@ -1,3 +1,12 @@
2003-12-15 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/gst.c: (init_popt_callback):
* gst/gstplugin.c: (_gst_plugin_fault_handler_restore),
(_gst_plugin_fault_handler_sighandler),
(_gst_plugin_fault_handler_setup), (gst_plugin_load_file):
Implemented fault handlers for catching SIGSEGV while loading
plug-ins
2003-12-02 Thomas Vander Stichele <thomas at apestaart dot org>
* fix documentation build using docbook2..., works on fc1 and rh9

View file

@ -55,6 +55,9 @@ static gboolean gst_initialized = FALSE;
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;
@ -96,6 +99,7 @@ enum {
ARG_PLUGIN_SPEW,
ARG_PLUGIN_PATH,
ARG_PLUGIN_LOAD,
ARG_SEGFAULT_ENABLE,
ARG_SCHEDULER,
ARG_REGISTRY
};
@ -122,6 +126,7 @@ static const struct poptOption gstreamer_options[] = {
{"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
@ -700,6 +705,9 @@ init_popt_callback (poptContext context, enum poptCallbackReason reason,
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;

View file

@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <signal.h>
#include "gst_private.h"
@ -39,6 +40,11 @@
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
@ -194,6 +200,71 @@ gst_plugin_register_func (GstPlugin *plugin, GModule *module, GstPluginDesc *des
return plugin;
}
/**
* _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
@ -201,7 +272,7 @@ gst_plugin_register_func (GstPlugin *plugin, GModule *module, GstPluginDesc *des
*
* 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)
@ -229,8 +300,8 @@ 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);
@ -278,10 +349,19 @@ gst_plugin_load_file (const gchar *filename, GError **error)
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,