]> git.sesse.net Git - vlc/commitdiff
Lazily resolve plugins during scanning
authorRémi Denis-Courmont <remi@remlab.net>
Thu, 12 May 2011 20:07:44 +0000 (23:07 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Thu, 12 May 2011 20:59:33 +0000 (23:59 +0300)
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.

src/modules/modules.c
src/modules/modules.h
src/posix/plugin.c
src/win32/plugin.c

index 8fac5faef774d3e1362abbb5ba68ced60fd16b5c..6be4edca7cc8f13dd3b5cfd4acb9cf1e0bf15bd2 100644 (file)
@@ -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
index d353561397cbdee1aea8bcd111e7e21ec4efd4eb..fd2e31ded6d5be9c3b16826dcff1cbc412a00be6 100644 (file)
@@ -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);
 
index 0f2634fb020b3a8ab072099b5ec6c79976a6950f..7dd827f57576d9f9c51d230236de9c8704d20098 100644 (file)
  * \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
index 81a692f371e42386d21ca3985b1f789fbff3f7d0..445dc66253634658971b312c1aad07cee19b2506 100644 (file)
@@ -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);