From: Mathieu Duponchelle Date: Mon, 25 Sep 2017 18:35:59 +0000 (+0200) Subject: plugin: API: GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE X-Git-Tag: 1.16.2~665 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6cddce7663cb4b6ee061950d20365f42cb755851;p=platform%2Fupstream%2Fgstreamer.git plugin: API: GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE When a plugin declares a dependency using this flag, all the relative paths are considered to be relative to the path of the main executable. We try to determine the path of the executable portably, with implementations provided for Linux, Windows and Mac. If retrieval of the path fails, we will not detect changes. In order for the main executable path to be the same when scanning a plugin in a child process, a new variable is exposed in gst_private.h, _gst_executable_path https://bugzilla.gnome.org/show_bug.cgi?id=788152 --- diff --git a/gst/gst.c b/gst/gst.c index e0225b4..26948da 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -106,6 +106,10 @@ #define WIN32_LEAN_AND_MEAN /* prevents from including too many things */ #include /* GetStdHandle, windows console */ #endif +#if defined (__APPLE__) +#include +#include /* proc_pidpath, PROC_PIDPATHINFO_MAXSIZE */ +#endif #include "gst-i18n-lib.h" #include /* for LC_ALL */ @@ -133,6 +137,8 @@ extern gboolean _priv_gst_disable_registry; extern gboolean _priv_gst_disable_registry_update; #endif +gchar *_gst_executable_path = NULL; + #ifndef GST_DISABLE_GST_DEBUG const gchar *priv_gst_dump_dot_dir; #endif @@ -311,6 +317,56 @@ gst_init_get_option_group (void) #endif } +#if defined(__linux__) +static void +find_executable_path (void) +{ + GError *error = NULL; + gchar *path; + + if (_gst_executable_path) + return; + + path = g_file_read_link ("/proc/self/exe", &error); + + if (path) { + _gst_executable_path = g_path_get_dirname (path); + g_free (path); + } +} +#elif defined(G_OS_WIN32) +static void +find_executable_path (void) +{ + char buffer[MAX_PATH]; + + if (!GetModuleFilename (NULL, buffer, MAX_PATH)) + return; + + _gst_executable_path = g_strdup (buffer); +} +#elif defined(__APPLE__) +static void +find_executable_path (void) +{ + int ret; + pid_t pid; + char pathbuf[PROC_PIDPATHINFO_MAXSIZE]; + + pid = getpid (); + ret = proc_pidpath (pid, pathbuf, sizeof (pathbuf)); + if (ret > 0) + _gst_executable_path = g_strdup (pathbuf) + } +#else +static void +find_executable_path (void) +{ + GST_FIXME ("Couldn't look up executable path, add support for this platform"); +} +#endif + + /** * gst_init_check: * @argc: (inout) (allow-none): pointer to application's argc @@ -343,6 +399,9 @@ gst_init_check (int *argc, char **argv[], GError ** err) g_mutex_unlock (&init_lock); return TRUE; } + + find_executable_path (); + #ifndef GST_DISABLE_OPTION_PARSING ctx = g_option_context_new ("- GStreamer initialization"); g_option_context_set_ignore_unknown_options (ctx, TRUE); @@ -1019,6 +1078,11 @@ gst_deinit (void) _priv_gst_plugin_paths = NULL; #endif + if (_gst_executable_path) { + g_free (_gst_executable_path); + _gst_executable_path = NULL; + } + clock = gst_system_clock_obtain (); gst_object_unref (clock); gst_object_unref (clock); diff --git a/gst/gst_private.h b/gst/gst_private.h index e88bb60..b2905a0 100644 --- a/gst/gst_private.h +++ b/gst/gst_private.h @@ -229,6 +229,10 @@ GstCapsFeatures * __gst_caps_get_features_unchecked (const GstCaps * caps, guint GST_EXPORT gboolean _gst_disable_registry_cache; #endif +/* Secret variable to let the plugin scanner use the same base path + * as the main application in order to determine dependencies */ +GST_EXPORT gchar *_gst_executable_path; + /* provide inline gst_g_value_get_foo_unchecked(), used in gststructure.c */ #define DEFINE_INLINE_G_VALUE_GET_UNCHECKED(ret_type,name_type,v_field) \ static inline ret_type \ diff --git a/gst/gstplugin.c b/gst/gstplugin.c index 6970fdf..18183c3 100644 --- a/gst/gstplugin.c +++ b/gst/gstplugin.c @@ -1702,6 +1702,7 @@ static guint gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep) { gboolean paths_are_default_only; + gboolean paths_are_relative_to_exe; GQueue scan_paths = G_QUEUE_INIT; guint scan_hash = 0; gchar *path; @@ -1710,6 +1711,8 @@ gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep) paths_are_default_only = dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY; + paths_are_relative_to_exe = + dep->flags & GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE; gst_plugin_ext_dep_extract_env_vars_paths (plugin, dep, &scan_paths); @@ -1718,12 +1721,26 @@ gst_plugin_ext_dep_get_stat_hash (GstPlugin * plugin, GstPluginDep * dep) for (paths = dep->paths; paths != NULL && *paths != NULL; ++paths) { const gchar *path = *paths; + gchar *full_path; + + if (paths_are_relative_to_exe && !g_path_is_absolute (path)) { + if (!_gst_executable_path) { + GST_FIXME_OBJECT (plugin, + "Path dependency %s relative to executable path but could not retrieve executable path", + path); + continue; + } + full_path = g_build_filename (_gst_executable_path, path, NULL); + } else { + full_path = g_strdup (path); + } - if (!g_queue_find_custom (&scan_paths, path, (GCompareFunc) strcmp)) { - GST_LOG_OBJECT (plugin, "path: '%s'", path); - g_queue_push_tail (&scan_paths, g_strdup (path)); + if (!g_queue_find_custom (&scan_paths, full_path, (GCompareFunc) strcmp)) { + GST_LOG_OBJECT (plugin, "path: '%s'", full_path); + g_queue_push_tail (&scan_paths, full_path); } else { - GST_LOG_OBJECT (plugin, "path: '%s' (duplicate, ignoring)", path); + GST_LOG_OBJECT (plugin, "path: '%s' (duplicate, ignoring)", full_path); + g_free (full_path); } } } diff --git a/gst/gstplugin.h b/gst/gstplugin.h index 7258388..691d5f6 100644 --- a/gst/gstplugin.h +++ b/gst/gstplugin.h @@ -98,6 +98,9 @@ typedef enum * @GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX : interpret * filename argument as filter prefix and check all matching files in * the directory. Since 1.8. + * @GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE : interpret + * non-absolute paths as relative to the main executable directory. Since + * 1.14. * * Flags used in connection with gst_plugin_add_dependency(). */ @@ -106,7 +109,8 @@ typedef enum { GST_PLUGIN_DEPENDENCY_FLAG_RECURSE = (1 << 0), GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_DEFAULT_ONLY = (1 << 1), GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_SUFFIX = (1 << 2), - GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX = (1 << 3) + GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX = (1 << 3), + GST_PLUGIN_DEPENDENCY_FLAG_PATHS_ARE_RELATIVE_TO_EXE = (1 << 4) } GstPluginDependencyFlags; /** diff --git a/gst/gstpluginloader.c b/gst/gstpluginloader.c index be40cb5..a933a4b 100644 --- a/gst/gstpluginloader.c +++ b/gst/gstpluginloader.c @@ -408,7 +408,7 @@ gst_plugin_loader_use_usr_bin_arch (void) static gboolean gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) { - char *argv[5] = { NULL, }; + char *argv[6] = { NULL, }; int c = 0; #if defined (__APPLE__) && defined (USR_BIN_ARCH_SWITCH) @@ -419,9 +419,10 @@ gst_plugin_loader_try_helper (GstPluginLoader * loader, gchar * location) #endif argv[c++] = location; argv[c++] = (char *) "-l"; + argv[c++] = _gst_executable_path; argv[c++] = NULL; - if (c > 3) { + if (c > 4) { GST_LOG ("Trying to spawn gst-plugin-scanner helper at %s with arch %s", location, argv[1]); } else { diff --git a/libs/gst/helpers/gst-plugin-scanner.c b/libs/gst/helpers/gst-plugin-scanner.c index b5b3980..cda1ac9 100644 --- a/libs/gst/helpers/gst-plugin-scanner.c +++ b/libs/gst/helpers/gst-plugin-scanner.c @@ -38,7 +38,7 @@ main (int argc, char *argv[]) char **my_argv; int my_argc; - if (argc != 2 || strcmp (argv[1], "-l")) + if (argc != 3 || strcmp (argv[1], "-l")) return 1; my_argc = 2; @@ -50,6 +50,7 @@ main (int argc, char *argv[]) _gst_disable_registry_cache = TRUE; #endif + _gst_executable_path = g_strdup (argv[2]); res = gst_init_check (&my_argc, &my_argv, NULL); g_free (my_argv); diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index d9007e9..a8d14f5 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -50,6 +50,7 @@ EXPORTS _gst_debug_nameof_funcptr _gst_debug_register_funcptr _gst_disable_registry_cache DATA + _gst_executable_path DATA _gst_double_range_type DATA _gst_element_error_printf _gst_event_type DATA