From 65d2183365ccbd6321ecb8fcbf8bbf42362ca1ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cl=C3=A9ment=20Stenac?= Date: Fri, 22 Dec 2006 21:14:11 +0000 Subject: [PATCH] Add facilities to report and enrich error messages. The idea is that a given error should be reported only once to the user. At the moment, for example, we can get: - "no suitable access module" (printed by module_Need) - "unable to create access" (printed by input/access) - "unable to open stream" (printed by input/input) - ... The facilities provided here are: * msg_StackSet( code, message ) : "throw" a new error * msg_StackAdd( message ) : Append a message allowing to trace the message * msg_StackMsg() : Retrieve the message So, in the previous example, module_Need would msg_StackSet( code, "no suitable access module"), then input/input would add "unable to create access" and finally, input/input can print the "unable to open stream: unable to create access: no suitable module" message. The three functions are context-free, you don't need a vlc_object, so that we can add verbose error reporting everywhere. --- include/vlc_common.h | 8 +++++ include/vlc_messages.h | 12 +++++++- include/vlc_threads.h | 4 +++ include/vlc_threads_funcs.h | 17 +++++------ src/input/access.c | 1 + src/input/input.c | 3 +- src/misc/messages.c | 61 +++++++++++++++++++++++++++++++++++++ src/misc/modules.c | 5 +++ src/misc/threads.c | 25 ++++++++------- 9 files changed, 111 insertions(+), 25 deletions(-) diff --git a/include/vlc_common.h b/include/vlc_common.h index d0a7672a80..4c8fd91ebb 100644 --- a/include/vlc_common.h +++ b/include/vlc_common.h @@ -1177,6 +1177,14 @@ VLC_EXPORT( const char *, VLC_Changeset, ( void ) ); #include "main.h" #include "vlc_configuration.h" +/** The global thread var for msg stack context + * We store this as a static global variable so we don't need a vlc_object_t + * everywhere. + * This key is created in vlc_threads_init and is therefore ready to use at + * the very beginning of the universe */ +extern vlc_threadvar_t msg_context_global_key; + + #if defined( __BORLANDC__ ) # undef PACKAGE # define PACKAGE diff --git a/include/vlc_messages.h b/include/vlc_messages.h index 6ad4c0a281..a08b12efb1 100644 --- a/include/vlc_messages.h +++ b/include/vlc_messages.h @@ -44,9 +44,19 @@ int vlc_mutex_unlock( vlc_mutex_t * ) ; * @{ */ +/** Internal message stack context */ +typedef struct +{ + int i_code; + char * psz_message; +} msg_context_t; + +VLC_EXPORT( void, msg_StackSet, ( int, const char*, ... ) ); +VLC_EXPORT( void, msg_StackAdd, ( const char*, ... ) ); +VLC_EXPORT( const char*, msg_StackMsg, ( void ) ); /** - * Store a single message. + * Store a single message sent to user. */ typedef struct { diff --git a/include/vlc_threads.h b/include/vlc_threads.h index 86edcdc991..20a5e78c15 100644 --- a/include/vlc_threads.h +++ b/include/vlc_threads.h @@ -29,6 +29,9 @@ #error You are not libvlc or one of its plugins. You cannot include this file #endif +#ifndef _VLC_THREADS_H_ +#define _VLC_THREADS_H_ + #include #if defined(DEBUG) && defined(HAVE_SYS_TIME_H) @@ -274,3 +277,4 @@ typedef struct #endif +#endif diff --git a/include/vlc_threads_funcs.h b/include/vlc_threads_funcs.h index 1e68fea6eb..c81713689f 100644 --- a/include/vlc_threads_funcs.h +++ b/include/vlc_threads_funcs.h @@ -29,6 +29,9 @@ #error You are not libvlc or one of its plugins. You cannot include this file #endif +#ifndef _VLC_THREADFUNCS_H_ +#define _VLC_THREADFUNCS_H_ + /***************************************************************************** * Function definitions *****************************************************************************/ @@ -557,11 +560,7 @@ static inline int __vlc_cond_wait( const char * psz_file, int i_line, /***************************************************************************** * vlc_threadvar_set: create: set the value of a thread-local variable *****************************************************************************/ -#define vlc_threadvar_set( P_TLS , P_VAL ) \ - __vlc_threadvar_set( __FILE__, __LINE__, P_TLS, P_VAL ) - -static inline int __vlc_threadvar_set( char* psz_file, int line, - vlc_threadvar_t * p_tls, void *p_value ) +static inline int vlc_threadvar_set( vlc_threadvar_t * p_tls, void *p_value ) { int i_ret; @@ -588,11 +587,7 @@ static inline int __vlc_threadvar_set( char* psz_file, int line, /***************************************************************************** * vlc_threadvar_get: create: get the value of a thread-local variable *****************************************************************************/ -#define vlc_threadvar_get( P_TLS ) \ - __vlc_threadvar_get( __FILE__, __LINE__, P_TLS ) - -static inline void* __vlc_threadvar_get( char* psz_file, int line, - vlc_threadvar_t * p_tls ) +static inline void* vlc_threadvar_get( vlc_threadvar_t * p_tls ) { void* p_ret; @@ -641,3 +636,5 @@ static inline void* __vlc_threadvar_get( char* psz_file, int line, *****************************************************************************/ #define vlc_thread_join( P_THIS ) \ __vlc_thread_join( VLC_OBJECT(P_THIS), __FILE__, __LINE__ ) + +#endif diff --git a/src/input/access.c b/src/input/access.c index 9ce14db09f..6a0a63453c 100644 --- a/src/input/access.c +++ b/src/input/access.c @@ -101,6 +101,7 @@ static access_t *access2_InternalNew( vlc_object_t *p_obj, const char *psz_acces if( p_access->p_module == NULL ) { + msg_StackAdd( "could not create access" ); vlc_object_detach( p_access ); free( p_access->psz_access ); free( p_access->psz_path ); diff --git a/src/input/input.c b/src/input/input.c index ec1a3f025e..7b63bd4cc9 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -2073,7 +2073,8 @@ static int InputSourceInit( input_thread_t *p_input, if( in->p_access == NULL ) { - msg_Err( p_input, "no suitable access module for `%s'", psz_mrl ); + msg_Err( p_input, "open of `%s' failed: %s", psz_mrl, + msg_StackMsg() ); intf_UserFatal( VLC_OBJECT( p_input), VLC_FALSE, _("Your input can't be opened"), _("VLC is unable to open the MRL '%s'." diff --git a/src/misc/messages.c b/src/misc/messages.c index 9f9b98c17e..6eeed09c8b 100644 --- a/src/misc/messages.c +++ b/src/misc/messages.c @@ -583,3 +583,64 @@ static void PrintMsg ( vlc_object_t * p_this, msg_item_t * p_item ) # endif #endif } + +static msg_context_t* GetContext(void) +{ + msg_context_t *p_ctx = vlc_threadvar_get( &msg_context_global_key ); + if( p_ctx == NULL ) + { + MALLOC_NULL( p_ctx, msg_context_t ); + p_ctx->psz_message = NULL; + vlc_threadvar_set( &msg_context_global_key, p_ctx ); + } + return p_ctx; +} + +void msg_StackSet( int i_code, const char *psz_message, ... ) +{ + va_list ap; + msg_context_t *p_ctx = GetContext(); + assert( p_ctx ); + va_start( ap, psz_message ); + if( p_ctx->psz_message != NULL ) + { + free( p_ctx->psz_message ); + } + + vasprintf( &p_ctx->psz_message, psz_message, ap ); + va_end( ap ); + p_ctx->i_code = i_code; +} + +void msg_StackAdd( const char *psz_message, ... ) +{ + char *psz_tmp; + va_list ap; + msg_context_t *p_ctx = GetContext(); + assert( p_ctx ); + + va_start( ap, psz_message ); + vasprintf( &psz_tmp, psz_message, ap ); + va_end( ap ); + + if( !p_ctx->psz_message ) + p_ctx->psz_message = psz_tmp; + else + { + char *psz_old = malloc( strlen( p_ctx->psz_message ) + 1 ); + memcpy( psz_old, p_ctx->psz_message, strlen( p_ctx->psz_message ) + 1 ); + p_ctx->psz_message = realloc( p_ctx->psz_message, + strlen( p_ctx->psz_message ) + + /* ':', ' ', '0' */ + strlen( psz_tmp ) + 3 ); + sprintf( p_ctx->psz_message, "%s: %s", psz_tmp, psz_old ); + free( psz_tmp ); free( psz_old ); + } +} + +const char* msg_StackMsg( void ) +{ + msg_context_t *p_ctx = GetContext(); + assert( p_ctx ); + return p_ctx->psz_message; +} diff --git a/src/misc/modules.c b/src/misc/modules.c index 2bd863bdab..b22a48209b 100644 --- a/src/misc/modules.c +++ b/src/misc/modules.c @@ -699,6 +699,9 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability, { msg_Err( p_this, "no %s module matched \"%s\"", psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); + + msg_StackSet( VLC_EGENERIC, "no %s module matched \"%s\"", + psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); } } else if( psz_name != NULL && *psz_name ) @@ -706,6 +709,8 @@ module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability, msg_Warn( p_this, "no %s module matching \"%s\" could be loaded", psz_capability, (psz_name && *psz_name) ? psz_name : "any" ); } + else + msg_StackSet( VLC_EGENERIC, "no suitable %s module", psz_capability ); if( psz_shortcuts ) { diff --git a/src/misc/threads.c b/src/misc/threads.c index fb3bab6b00..fe4c7392cf 100644 --- a/src/misc/threads.c +++ b/src/misc/threads.c @@ -49,6 +49,8 @@ static vlc_object_t *p_root; #elif defined( HAVE_CTHREADS_H ) #endif +vlc_threadvar_t msg_context_global_key; + /***************************************************************************** * vlc_threads_init: initialize threads system ***************************************************************************** @@ -130,6 +132,8 @@ int __vlc_threads_init( vlc_object_t *p_this ) i_initializations++; i_status = VLC_THREADS_READY; } + + vlc_threadvar_create( p_root, &msg_context_global_key ); } else { @@ -505,30 +509,25 @@ int __vlc_cond_destroy( const char * psz_file, int i_line, vlc_cond_t *p_condvar *****************************************************************************/ int __vlc_threadvar_create( vlc_object_t *p_this, vlc_threadvar_t *p_tls ) { + int i_ret; #if defined( PTH_INIT_IN_PTH_H ) - return pth_key_create( &p_tls->handle, NULL ); + i_ret = pth_key_create( &p_tls->handle, NULL ); #elif defined( HAVE_KERNEL_SCHEDULER_H ) msg_Err( p_this, "TLS not implemented" ); - return VLC_EGENERIC; + i_ret VLC_EGENERIC; #elif defined( ST_INIT_IN_ST_H ) - return st_key_create( &p_tls->handle, NULL ); + i_ret = st_key_create( &p_tls->handle, NULL ); #elif defined( UNDER_CE ) || defined( WIN32 ) #elif defined( WIN32 ) p_tls->handle = TlsAlloc(); - if( p_tls->handle == 0xFFFFFFFF ) - { - return VLC_EGENERIC; - } - - msg_Err( p_this, "TLS not implemented" ); - return VLC_EGENERIC; + i_ret = !( p_tls->handle == 0xFFFFFFFF ); #elif defined( PTHREAD_COND_T_IN_PTHREAD_H ) - return pthread_key_create( &p_tls->handle, NULL ); - + i_ret = pthread_key_create( &p_tls->handle, NULL ); #elif defined( HAVE_CTHREADS_H ) - return cthread_keycreate( &p_tls-handle ); + i_ret = cthread_keycreate( &p_tls-handle ); #endif + return i_ret; } /***************************************************************************** -- 2.39.2