From: Thomas V. S. <tho...@us...> - 2003-12-15 12:44:48
|
CVS Root: /cvsroot/gstreamer Module: gstreamer Changes by: thomasvs Date: Mon Dec 15 2003 04:44:47 PST Log message: implementing segfault handler for plugin loading Modified files: . : ChangeLog gst : gst.c gstplugin.c Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/ChangeLog.diff?r1=1.29&r2=1.30 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/gst/gst.c.diff?r1=1.114&r2=1.115 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gstreamer/gst/gstplugin.c.diff?r1=1.109&r2=1.110 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/ChangeLog,v retrieving revision 1.29 retrieving revision 1.30 diff -u -d -r1.29 -r1.30 --- ChangeLog 2 Dec 2003 18:21:32 -0000 1.29 +++ ChangeLog 15 Dec 2003 12:44:34 -0000 1.30 @@ -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 Index: gst.c =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/gst/gst.c,v retrieving revision 1.114 retrieving revision 1.115 diff -u -d -r1.114 -r1.115 --- gst.c 9 Dec 2003 02:39:30 -0000 1.114 +++ gst.c 15 Dec 2003 12:44:35 -0000 1.115 @@ -55,6 +55,9 @@ 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 @@ ARG_PLUGIN_SPEW, ARG_PLUGIN_PATH, ARG_PLUGIN_LOAD, + ARG_SEGFAULT_ENABLE, ARG_SCHEDULER, ARG_REGISTRY }; @@ -122,6 +126,7 @@ {"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 @@ -699,6 +704,9 @@ break; 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); Index: gstplugin.c =================================================================== RCS file: /cvsroot/gstreamer/gstreamer/gst/gstplugin.c,v retrieving revision 1.109 retrieving revision 1.110 diff -u -d -r1.109 -r1.110 --- gstplugin.c 4 Dec 2003 10:02:26 -0000 1.109 +++ gstplugin.c 15 Dec 2003 12:44:35 -0000 1.110 @@ -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 gst...@li... if your license should be @@ -195,13 +201,78 @@ } /** + * _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) @@ -229,8 +300,8 @@ 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 @@ 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, |