]> git.sesse.net Git - vlc/commitdiff
Add facilities to report and enrich error messages.
authorClément Stenac <zorglub@videolan.org>
Fri, 22 Dec 2006 21:14:11 +0000 (21:14 +0000)
committerClément Stenac <zorglub@videolan.org>
Fri, 22 Dec 2006 21:14:11 +0000 (21:14 +0000)
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
include/vlc_messages.h
include/vlc_threads.h
include/vlc_threads_funcs.h
src/input/access.c
src/input/input.c
src/misc/messages.c
src/misc/modules.c
src/misc/threads.c

index d0a7672a80e0aeeb67f4ce955686259b7174b12b..4c8fd91ebbf91092c61d6c32348d05fceb031483 100644 (file)
@@ -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
index 6ad4c0a281ff7d15fd99a13fb0390f4d821a5ccd..a08b12efb18d01a6d7181052472e987ee75b919f 100644 (file)
@@ -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
 {
index 86edcdc99119a5a31bdf6e941c313a7864b8b5ff..20a5e78c157111df2f88bd659d1e0bf61e5c87c5 100644 (file)
@@ -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 <stdio.h>
 
 #if defined(DEBUG) && defined(HAVE_SYS_TIME_H)
@@ -274,3 +277,4 @@ typedef struct
 
 #endif
 
+#endif
index 1e68fea6eb709ea974d2f104830ed603e9242ab6..c81713689fc0bb99f878d2f19ed6e2f6bd5fbd2a 100644 (file)
@@ -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
index 9ce14db09fe2a7764f15550158d7ee0d974c0d3a..6a0a63453c472d9991ea34716973650838efec41 100644 (file)
@@ -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 );
index ec1a3f025e6642be555a48ffbf2e235e64efa415..7b63bd4cc9d63ae8279e4bbb410cb99bd966e1f7 100644 (file)
@@ -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'."
index 9f9b98c17e475172b2182dc0aea60be02f650e23..6eeed09c8b81e5d166c9deb244f48f0cd9ef0e09 100644 (file)
@@ -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;
+}
index 2bd863bdabe750522e33ea6a74733201b81a67c7..b22a48209b977b63e291dcca234b9aff33482ff5 100644 (file)
@@ -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 )
     {
index fb3bab6b00d65e14cefc1a568030455ecf50c995..fe4c7392cfeb8e49591e13534683f5662c519907 100644 (file)
@@ -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;
 }
 
 /*****************************************************************************