[vlc-commits] Lazily resolve plugins during scanning

Rémi Denis-Courmont git at videolan.org
Thu May 12 23:02:13 CEST 2011


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu May 12 23:07:44 2011 +0300| [8277183cd5250e0ce5fef2528cf7e4e35eea2bd6] | committer: Rémi Denis-Courmont

Lazily resolve plugins during scanning

There are two advantages:
 - scanning uncached plugins is much faster,
 - plugins with broken dependencies are visible in the modules list.

Plugins are still resolved "now" if they are probed by module_need().
This is a safety feature (the run-time linker would exit silently if it
hit an unresolved symbol). As the previous commit unloads all uncached
plugins, we can reload the plugins with different flags as needed.

Plugins with broken/missing underlying libraries will trigger an error
only when used, rather than when scanned. vlc-cache-gen is then a bit
more robust against messed up packages installation (it will not skip
plugins anymore). Also, dialog_Fatal() could be used to report run-time
errors. This was not possible previously: the error would occur before
the UI was started.

Note that this is not implemented on Windows, as there is no support
(that I know) for lazy resolution of DLLs.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=8277183cd5250e0ce5fef2528cf7e4e35eea2bd6
---

 src/modules/modules.c |   36 ++++++++++++++++++------------------
 src/modules/modules.h |    2 +-
 src/posix/plugin.c    |    4 ++--
 src/win32/plugin.c    |    3 ++-
 4 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/src/modules/modules.c b/src/modules/modules.c
index 8fac5fa..6be4edc 100644
--- a/src/modules/modules.c
+++ b/src/modules/modules.c
@@ -75,7 +75,7 @@ static void AllocatePluginDir( vlc_object_t *, module_bank_t *, const char *,
                                unsigned, cache_mode_t );
 static int  AllocatePluginFile( vlc_object_t *, module_bank_t *, const char *,
                                 time_t, off_t, cache_mode_t );
-static module_t * AllocatePlugin( vlc_object_t *, const char * );
+static module_t * AllocatePlugin( vlc_object_t *, const char *, bool );
 #endif
 static int  AllocateBuiltinModule( vlc_object_t *, int ( * ) ( module_t * ) );
 static void DeleteModule ( module_bank_t *, module_t * );
@@ -555,7 +555,7 @@ found_shortcut:
         if( !p_real->b_builtin && !p_real->b_loaded )
         {
             module_t *p_new_module =
-                AllocatePlugin( p_this, p_real->psz_filename );
+                AllocatePlugin( p_this, p_real->psz_filename, false );
             if( p_new_module == NULL )
             {   /* Corrupted module */
                 msg_Err( p_this, "possibly corrupt module cache" );
@@ -972,7 +972,7 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank,
     if( mode == CACHE_USE )
         p_module = CacheFind( p_bank, path, mtime, size );
     if( p_module == NULL )
-        p_module = AllocatePlugin( p_this, path );
+        p_module = AllocatePlugin( p_this, path, true );
     if( p_module == NULL )
         return -1;
 
@@ -986,27 +986,26 @@ static int AllocatePluginFile( vlc_object_t * p_this, module_bank_t *p_bank,
     p_bank->head = p_module;
     assert( p_module->next != NULL ); /* Insertion done */
 
+    /* Unload plugin until we really need it */
+    if( p_module->b_loaded && p_module->b_unloadable )
+    {
+        module_Unload( p_module->handle );
+        p_module->b_loaded = false;
+    }
+
     /* For now we force loading if the module's config contains
      * callbacks or actions.
      * Could be optimized by adding an API call.*/
     for( size_t n = p_module->confsize, i = 0; i < n; i++ )
          if( p_module->p_config[i].i_action )
          {
-             if( !p_module->b_loaded )
-             {
-                 DeleteModule( p_bank, p_module );
-                 p_module = AllocatePlugin( p_this, path );
-             }
-             goto keep;
+             /* !unloadable not allowed for plugins with callbacks */
+             assert( !p_module->b_loaded );
+             DeleteModule( p_bank, p_module );
+             p_module = AllocatePlugin( p_this, path, false );
+             break;
          }
 
-    /* Unload plugin until we really need it */
-    if( p_module->b_loaded && p_module->b_unloadable )
-    {
-        module_Unload( p_module->handle );
-        p_module->b_loaded = false;
-    }
-keep:
     if( mode == CACHE_IGNORE )
         return 0;
 
@@ -1035,12 +1034,13 @@ keep:
  * for its information data. The module can then be handled by module_need
  * and module_unneed. It can be removed by DeleteModule.
  *****************************************************************************/
-static module_t * AllocatePlugin( vlc_object_t * p_this, const char *psz_file )
+static module_t *AllocatePlugin( vlc_object_t * p_this, const char *psz_file,
+                                 bool fast )
 {
     module_t * p_module = NULL;
     module_handle_t handle;
 
-    if( module_Load( p_this, psz_file, &handle ) )
+    if( module_Load( p_this, psz_file, &handle, fast ) )
         return NULL;
 
     /* Now that we have successfully loaded the module, we can
diff --git a/src/modules/modules.h b/src/modules/modules.h
index d353561..fd2e31d 100644
--- a/src/modules/modules.h
+++ b/src/modules/modules.h
@@ -141,7 +141,7 @@ void module_EndBank( vlc_object_t *, bool );
 int vlc_bindtextdomain (const char *);
 
 /* Low-level OS-dependent handler */
-int module_Load (vlc_object_t *, const char *, module_handle_t *);
+int module_Load (vlc_object_t *, const char *, module_handle_t *, bool);
 void *module_Lookup (module_handle_t, const char *);
 void module_Unload (module_handle_t);
 
diff --git a/src/posix/plugin.c b/src/posix/plugin.c
index 0f2634f..7dd827f 100644
--- a/src/posix/plugin.c
+++ b/src/posix/plugin.c
@@ -48,10 +48,10 @@
  * \return 0 on success as well as the module handle.
  */
 int module_Load( vlc_object_t *p_this, const char *psz_file,
-                 module_handle_t *p_handle )
+                 module_handle_t *p_handle, bool lazy )
 {
 #if defined (RTLD_NOW)
-    const int flags = RTLD_NOW;
+    const int flags = lazy ? RTLD_LAZY : RTLD_NOW;
 #elif defined (DL_LAZY)
     const int flags = DL_LAZY;
 #else
diff --git a/src/win32/plugin.c b/src/win32/plugin.c
index 81a692f..445dc66 100644
--- a/src/win32/plugin.c
+++ b/src/win32/plugin.c
@@ -51,13 +51,14 @@ static char *GetWindowsError( void )
 }
 
 int module_Load( vlc_object_t *p_this, const char *psz_file,
-                 module_handle_t *p_handle )
+                 module_handle_t *p_handle, bool lazy )
 {
     module_handle_t handle;
 
     wchar_t psz_wfile[MAX_PATH];
     MultiByteToWideChar( CP_UTF8, 0, psz_file, -1, psz_wfile, MAX_PATH );
 
+    (void) lazy;
 #ifndef UNDER_CE
     /* FIXME: this is not thread-safe -- Courmisch */
     UINT mode = SetErrorMode (SEM_FAILCRITICALERRORS);



More information about the vlc-commits mailing list