Commit 8277183c authored by Rémi Denis-Courmont's avatar 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.
parent a9093a20
......@@ -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
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment