From ed43ab15094a0ca8d01e35b87de4eeca579b50ef Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 4 Feb 2015 14:30:05 +0100 Subject: [PATCH] validate: Implement fault_injection as a Gs(tValidate)Plugin https://bugzilla.gnome.org/show_bug.cgi?id=743994 --- validate/configure.ac | 15 ++- validate/fault_injection/Makefile.am | 14 +- validate/fault_injection/socket_interposer.c | 25 +++- validate/fault_injection/socket_interposer.h | 2 - validate/gst/validate/Makefile.am | 6 +- validate/gst/validate/gst-validate-scenario.c | 3 - validate/gst/validate/validate.c | 120 ++++++++++++++++++ 7 files changed, 158 insertions(+), 27 deletions(-) diff --git a/validate/configure.ac b/validate/configure.ac index ea310bf746..ca34dc8a8c 100644 --- a/validate/configure.ac +++ b/validate/configure.ac @@ -188,8 +188,15 @@ GST_LICENSE="LGPL" AC_DEFINE_UNQUOTED(GST_LICENSE, "$GST_LICENSE", [GStreamer license]) AC_SUBST(GST_LICENSE) -dnl set location of plugin directory -AG_GST_SET_PLUGINDIR +dnl define location of plugin directory +AS_AC_EXPAND(PLUGINDIR, ${libdir}/gstreamer-$GST_API_VERSION/validate) +AC_DEFINE_UNQUOTED(PLUGINDIR, "$PLUGINDIR", +[directory where GstValidate plugins are located]) +AC_MSG_NOTICE([Using $PLUGINDIR as the plugin install location for GstValidate]) + +dnl plugin directory configure-time variable for use in Makefile.am +plugindir="\$(libdir)/gstreamer-$GST_API_VERSION/validate" +AC_SUBST(plugindir) # set by AG_GST_PARSE_SUBSYSTEM_DISABLES above dnl make sure it doesn't complain about unused variables if debugging is disabled @@ -235,10 +242,6 @@ GST_CFLAGS="$GST_CFLAGS \$(GST_OPTION_CFLAGS)" AC_SUBST(GST_CFLAGS) AC_SUBST(GST_LIBS) -dnl Tiny library overriding calls such as socket recv / send -FAULTINJECTION_LIBS="-L\$(top_srcdir)/fault_injection/ -lfaultinjection-$GST_API_VERSION" -AC_SUBST([FAULTINJECTION_LIBS]) - dnl GST_ALL_* dnl vars common to for all internal objects (core libs, elements, applications) dnl CFLAGS: diff --git a/validate/fault_injection/Makefile.am b/validate/fault_injection/Makefile.am index dbfe5bef60..8a4302816f 100644 --- a/validate/fault_injection/Makefile.am +++ b/validate/fault_injection/Makefile.am @@ -1,13 +1,13 @@ -libfaultinjection_@GST_API_VERSION@_la_SOURCES = \ +plugin_LTLIBRARIES = libfaultinjection.la + +libfaultinjection_la_SOURCES = \ socket_interposer.c -libfaultinjection_@GST_API_VERSION@include_HEADERS = \ +noinst_HEADERS = \ socket_interposer.h -lib_LTLIBRARIES = libfaultinjection-@GST_API_VERSION@.la - -libfaultinjection_@GST_API_VERSION@_la_CFLAGS = $(GST_ALL_CFLAGS) -libfaultinjection_@GST_API_VERSION@_la_LIBADD = $(GST_ALL_LIBS) -libfaultinjection_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/faultinjection +libfaultinjection_la_CFLAGS = $(GST_ALL_CFLAGS) +libfaultinjection_la_LIBADD = $(GST_ALL_LIBS) $(top_builddir)/gst/validate/libgstvalidate-@GST_API_VERSION@.la +libfaultinjection_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GST_ALL_LDFLAGS) CLEANFILES = diff --git a/validate/fault_injection/socket_interposer.c b/validate/fault_injection/socket_interposer.c index 1d80287d6d..6e027d5512 100644 --- a/validate/fault_injection/socket_interposer.c +++ b/validate/fault_injection/socket_interposer.c @@ -24,8 +24,13 @@ #define _GNU_SOURCE +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "socket_interposer.h" -#include +#include +#include "../gst/validate/gst-validate-scenario.h" #if defined(__gnu_linux__) && !defined(__ANDROID__) && !defined (ANDROID) @@ -329,8 +334,8 @@ _execute_corrupt_socket_recv (GstValidateScenario * scenario, return GST_VALIDATE_EXECUTE_ACTION_ASYNC; } -void -socket_interposer_init (void) +static gboolean +socket_interposer_init (GstPlugin * plugin) { gst_validate_register_action_type ("corrupt-socket-recv", "fault-injector", _execute_corrupt_socket_recv, ((GstValidateActionParameter[]) { @@ -347,13 +352,23 @@ socket_interposer_init (void) NULL} }), "corrupt the next socket receive", GST_VALIDATE_ACTION_TYPE_ASYNC); + + return TRUE; } #else /* No LD_PRELOAD tricks on Windows */ -void -socket_interposer_init (void) +static gboolean +socket_interposer_init (GstPlugin * plugin) { + return TRUE; } #endif + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + faultinjector, + "Fault injector plugin for GstValidate", + socket_interposer_init, VERSION, "LGPL", GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/validate/fault_injection/socket_interposer.h b/validate/fault_injection/socket_interposer.h index 9bd3bd6eac..bc0857856d 100644 --- a/validate/fault_injection/socket_interposer.h +++ b/validate/fault_injection/socket_interposer.h @@ -24,6 +24,4 @@ #ifndef _SOCKET_INTERPOSER_H_ #define _SOCKET_INTERPOSER_H_ -extern void socket_interposer_init(void); - #endif /* _SOCKET_INTERPOSER_H_ */ diff --git a/validate/gst/validate/Makefile.am b/validate/gst/validate/Makefile.am index 7cdcddf7c9..e8e35c901a 100644 --- a/validate/gst/validate/Makefile.am +++ b/validate/gst/validate/Makefile.am @@ -46,14 +46,13 @@ noinst_HEADERS = \ lib_LTLIBRARIES = libgstvalidate-@GST_API_VERSION@.la libgstvalidate_@GST_API_VERSION@_la_CFLAGS = $(GST_ALL_CFLAGS)\ - $(GIO_CFLAGS) $(GST_PBUTILS_CFLAGS) -I$(top_srcdir)/fault_injection + $(GIO_CFLAGS) $(GST_PBUTILS_CFLAGS) libgstvalidate_@GST_API_VERSION@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) \ $(GST_LT_LDFLAGS) $(GIO_LDFLAGS) $(GST_PBUTILS_LDFAGS) libgstvalidate_@GST_API_VERSION@_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \ $(GST_ALL_LIBS) $(GIO_LIBS) $(GST_PBUTILS_LIBS) \ - $(GLIB_LIBS) $(LIBM)\ - $(FAULTINJECTION_LIBS) + $(GLIB_LIBS) $(LIBM) libgstvalidate_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/validate @@ -116,7 +115,6 @@ typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_API_VERSION@` \ --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-controller-@GST_API_VERSION@` \ --includedir=`$(PKG_CONFIG) --variable=girdir gio-2.0` \ - --shared-library=faultinjection-@GST_API_VERSION@ \ $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) endif diff --git a/validate/gst/validate/gst-validate-scenario.c b/validate/gst/validate/gst-validate-scenario.c index e45850e8cf..adc26560a6 100644 --- a/validate/gst/validate/gst-validate-scenario.c +++ b/validate/gst/validate/gst-validate-scenario.c @@ -45,7 +45,6 @@ #include "gst-validate-utils.h" #include #include -#include #define GST_VALIDATE_SCENARIO_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_VALIDATE_SCENARIO, GstValidateScenarioPrivate)) @@ -2653,6 +2652,4 @@ init_scenarios (void) GST_VALIDATE_ACTION_TYPE_NONE); /* *INDENT-ON* */ - socket_interposer_init (); - /* *INDENT-ON* */ } diff --git a/validate/gst/validate/validate.c b/validate/gst/validate/validate.c index 1a0376cb45..479ea2ea38 100644 --- a/validate/gst/validate/validate.c +++ b/validate/gst/validate/validate.c @@ -29,11 +29,129 @@ # include "config.h" #endif +/* For g_stat () */ +#include +#include +#include +#include + #include "validate.h" #include "gst-validate-internal.h" GST_DEBUG_CATEGORY (gstvalidate_debug); +static gboolean +gst_validate_scan_path_for_plugins (const gchar * path) +{ + GDir *dir; + const gchar *dirent; + gchar *filename; + GstPlugin *plugin; + gboolean changed = FALSE; + + dir = g_dir_open (path, 0, NULL); + if (!dir) + return FALSE; + + while ((dirent = g_dir_read_name (dir))) { + GStatBuf file_status; + + filename = g_build_filename (path, dirent, NULL); + if (g_stat (filename, &file_status) < 0) { + /* Plugin will be removed from cache after the scan completes if it + * is still marked 'cached' */ + g_free (filename); + continue; + } + + if (!(file_status.st_mode & S_IFREG)) { + g_free (filename); + continue; + } + if (!g_str_has_suffix (dirent, G_MODULE_SUFFIX)) { + GST_TRACE ("extension is not recognized as module file, ignoring file %s", + filename); + g_free (filename); + continue; + } + + plugin = gst_plugin_load_file (filename, NULL); + if (plugin) { + GST_DEBUG ("Plugin %s loaded", filename); + gst_object_unref (plugin); + } + + g_free (filename); + } + + g_dir_close (dir); + + return changed; + +} + + +static void +gst_validate_init_plugins (void) +{ + const gchar *plugin_path; + + plugin_path = g_getenv ("GST_VALIDATE_PLUGIN_PATH"); + if (plugin_path) { + char **list; + int i; + + GST_DEBUG ("GST_VALIDATE_PLUGIN_PATH set to %s", plugin_path); + list = g_strsplit (plugin_path, G_SEARCHPATH_SEPARATOR_S, 0); + for (i = 0; list[i]; i++) { + gst_validate_scan_path_for_plugins (list[i]); + } + g_strfreev (list); + } else { + GST_DEBUG ("GST_VALIDATE_PLUGIN_PATH not set"); + } + + if (plugin_path == NULL) { + char *home_plugins; + + /* plugins in the user's home directory take precedence over + * system-installed ones */ + home_plugins = g_build_filename (g_get_user_data_dir (), + "gstreamer-" GST_API_VERSION, "plugins", NULL); + + GST_DEBUG ("scanning home plugins %s", home_plugins); + gst_validate_scan_path_for_plugins (home_plugins); + g_free (home_plugins); + + /* add the main (installed) library path */ + +#ifdef G_OS_WIN32 + { + char *base_dir; + char *dir; + + base_dir = + g_win32_get_package_installation_directory_of_module + (_priv_gst_dll_handle); + + dir = g_build_filename (base_dir, +#ifdef _DEBUG + "debug" +#endif + "lib", "gstreamer-" GST_API_VERSION, NULL); + GST_DEBUG ("scanning DLL dir %s", dir); + + gst_validate_scan_path_for_plugins (dir); + + g_free (dir); + g_free (base_dir); + } +#else + gst_validate_scan_path_for_plugins (PLUGINDIR); +#endif + } +} + /** * gst_validate_init: * @@ -55,4 +173,6 @@ gst_validate_init (void) /* Ensure we load overrides before any use of a monitor */ gst_validate_override_registry_preload (); + + gst_validate_init_plugins (); }