Commit 2ec60e08 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Object functions: cancellation safety

parent 40c8f3c3
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
/** /**
* \file * \file
* This file contains the functions to handle the vlc_object_t type * This file contains the functions to handle the vlc_object_t type
*
* Unless otherwise stated, functions in this file are not cancellation point.
* All functions in this file are safe w.r.t. deferred cancellation.
*/ */
...@@ -97,6 +100,13 @@ static void held_objects_destroy (void *); ...@@ -97,6 +100,13 @@ static void held_objects_destroy (void *);
static vlc_mutex_t structure_lock; static vlc_mutex_t structure_lock;
static unsigned object_counter = 0; static unsigned object_counter = 0;
static void close_nocancel (int fd)
{
int canc = vlc_savecancel ();
close (fd);
vlc_restorecancel (canc);
}
void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size, void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size,
int i_type, const char *psz_type ) int i_type, const char *psz_type )
{ {
...@@ -200,12 +210,14 @@ void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size, ...@@ -200,12 +210,14 @@ void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size,
if( i_type == VLC_OBJECT_LIBVLC ) if( i_type == VLC_OBJECT_LIBVLC )
{ {
int canc = vlc_savecancel ();
var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_Create( p_new, "list", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
var_AddCallback( p_new, "list", DumpCommand, NULL ); var_AddCallback( p_new, "list", DumpCommand, NULL );
var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_Create( p_new, "tree", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
var_AddCallback( p_new, "tree", DumpCommand, NULL ); var_AddCallback( p_new, "tree", DumpCommand, NULL );
var_Create( p_new, "vars", VLC_VAR_STRING | VLC_VAR_ISCOMMAND ); var_Create( p_new, "vars", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
var_AddCallback( p_new, "vars", DumpCommand, NULL ); var_AddCallback( p_new, "vars", DumpCommand, NULL );
vlc_restorecancel (canc);
} }
return p_new; return p_new;
...@@ -289,6 +301,8 @@ void __vlc_object_set_destructor( vlc_object_t *p_this, ...@@ -289,6 +301,8 @@ void __vlc_object_set_destructor( vlc_object_t *p_this,
* This function destroys an object that has been previously allocated with * This function destroys an object that has been previously allocated with
* vlc_object_create. The object's refcount must be zero and it must not be * vlc_object_create. The object's refcount must be zero and it must not be
* attached to other objects in any way. * attached to other objects in any way.
*
* This function must be called with cancellation disabled (currently).
*****************************************************************************/ *****************************************************************************/
static void vlc_object_destroy( vlc_object_t *p_this ) static void vlc_object_destroy( vlc_object_t *p_this )
{ {
...@@ -516,6 +530,9 @@ int __vlc_object_waitpipe( vlc_object_t *obj ) ...@@ -516,6 +530,9 @@ int __vlc_object_waitpipe( vlc_object_t *obj )
* If the object was signaled before the caller locked the object, it is * If the object was signaled before the caller locked the object, it is
* undefined whether the signal will be lost or will wake the process. * undefined whether the signal will be lost or will wake the process.
* *
* This function is a cancellation point. In case of cancellation, the object
* will be in locked state.
*
* @return true if the object is dying and should terminate. * @return true if the object is dying and should terminate.
*/ */
void __vlc_object_wait( vlc_object_t *obj ) void __vlc_object_wait( vlc_object_t *obj )
...@@ -530,6 +547,9 @@ void __vlc_object_wait( vlc_object_t *obj ) ...@@ -530,6 +547,9 @@ void __vlc_object_wait( vlc_object_t *obj )
* Waits for the object to be signaled (using vlc_object_signal()), or for * Waits for the object to be signaled (using vlc_object_signal()), or for
* a timer to expire. It is asserted that the caller holds the object lock. * a timer to expire. It is asserted that the caller holds the object lock.
* *
* This function is a cancellation point. In case of cancellation, the object
* will be in locked state.
*
* @return 0 if the object was signaled before the timer expiration, or * @return 0 if the object was signaled before the timer expiration, or
* ETIMEDOUT if the timer expired without any signal. * ETIMEDOUT if the timer expired without any signal.
*/ */
...@@ -575,7 +595,7 @@ void __vlc_object_kill( vlc_object_t *p_this ) ...@@ -575,7 +595,7 @@ void __vlc_object_kill( vlc_object_t *p_this )
if( fd != -1 ) if( fd != -1 )
{ {
msg_Dbg (p_this, "waitpipe: object killed"); msg_Dbg (p_this, "waitpipe: object killed");
close (fd); close_nocancel (fd);
} }
vlc_object_signal_unlocked( p_this ); vlc_object_signal_unlocked( p_this );
...@@ -603,8 +623,12 @@ void * vlc_object_get( int i_id ) ...@@ -603,8 +623,12 @@ void * vlc_object_get( int i_id )
if (caller) if (caller)
msg_Dbg (caller, "uses deprecated vlc_object_get(%d)", i_id); msg_Dbg (caller, "uses deprecated vlc_object_get(%d)", i_id);
else else
{
int canc = vlc_savecancel ();
fprintf (stderr, "main thread uses deprecated vlc_object_get(%d)\n", fprintf (stderr, "main thread uses deprecated vlc_object_get(%d)\n",
i_id); i_id);
vlc_restorecancel (canc);
}
#endif #endif
vlc_mutex_lock( &structure_lock ); vlc_mutex_lock( &structure_lock );
...@@ -745,7 +769,7 @@ void __vlc_object_yield( vlc_object_t *p_this ) ...@@ -745,7 +769,7 @@ void __vlc_object_yield( vlc_object_t *p_this )
} }
/***************************************************************************** /*****************************************************************************
* decrement an object refcount * Decrement an object refcount
* And destroy the object if its refcount reach zero. * And destroy the object if its refcount reach zero.
*****************************************************************************/ *****************************************************************************/
void __vlc_object_release( vlc_object_t *p_this ) void __vlc_object_release( vlc_object_t *p_this )
...@@ -814,10 +838,14 @@ void __vlc_object_release( vlc_object_t *p_this ) ...@@ -814,10 +838,14 @@ void __vlc_object_release( vlc_object_t *p_this )
if( b_should_destroy ) if( b_should_destroy )
{ {
int canc;
free( internals->pp_children ); free( internals->pp_children );
internals->pp_children = NULL; internals->pp_children = NULL;
internals->i_children = 0; internals->i_children = 0;
canc = vlc_savecancel ();
vlc_object_destroy( p_this ); vlc_object_destroy( p_this );
vlc_restorecancel (canc);
} }
} }
...@@ -1272,6 +1300,7 @@ static void PrintObject( vlc_object_t *p_this, const char *psz_prefix ) ...@@ -1272,6 +1300,7 @@ static void PrintObject( vlc_object_t *p_this, const char *psz_prefix )
char psz_children[20], psz_refcount[20], psz_thread[30], psz_name[50], char psz_children[20], psz_refcount[20], psz_thread[30], psz_name[50],
psz_parent[20]; psz_parent[20];
int canc = vlc_savecancel ();
memset( &psz_name, 0, sizeof(psz_name) ); memset( &psz_name, 0, sizeof(psz_name) );
if( p_this->psz_object_name ) if( p_this->psz_object_name )
{ {
...@@ -1312,6 +1341,7 @@ static void PrintObject( vlc_object_t *p_this, const char *psz_prefix ) ...@@ -1312,6 +1341,7 @@ static void PrintObject( vlc_object_t *p_this, const char *psz_prefix )
p_this->i_object_id, p_this->psz_object_type, p_this->i_object_id, p_this->psz_object_type,
psz_name, psz_thread, psz_refcount, psz_children, psz_name, psz_thread, psz_refcount, psz_children,
psz_parent ); psz_parent );
vlc_restorecancel (canc);
} }
static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo ) static void DumpStructure( vlc_object_t *p_this, int i_level, char *psz_foo )
...@@ -1509,6 +1539,8 @@ void vlc_refcheck (vlc_object_t *obj) ...@@ -1509,6 +1539,8 @@ void vlc_refcheck (vlc_object_t *obj)
if (hlcur->obj == obj) if (hlcur->obj == obj)
return; return;
int canc = vlc_savecancel ();
fprintf (stderr, "The %s %s thread object is accessing...\n" fprintf (stderr, "The %s %s thread object is accessing...\n"
"the %s %s object without references.\n", "the %s %s object without references.\n",
caller && caller->psz_object_name caller && caller->psz_object_name
...@@ -1526,6 +1558,7 @@ void vlc_refcheck (vlc_object_t *obj) ...@@ -1526,6 +1558,7 @@ void vlc_refcheck (vlc_object_t *obj)
if (++errors == 100) if (++errors == 100)
fprintf (stderr, "Too many reference errors!\n"); fprintf (stderr, "Too many reference errors!\n");
vlc_restorecancel (canc);
} }
static void held_objects_destroy (void *data) static void held_objects_destroy (void *data)
...@@ -1534,6 +1567,8 @@ static void held_objects_destroy (void *data) ...@@ -1534,6 +1567,8 @@ static void held_objects_destroy (void *data)
held_list_t *hl = vlc_threadvar_get (&held_objects); held_list_t *hl = vlc_threadvar_get (&held_objects);
vlc_object_t *caller = vlc_threadobj (); vlc_object_t *caller = vlc_threadobj ();
int canc = vlc_savecancel ();
while (hl != NULL) while (hl != NULL)
{ {
held_list_t *buf = hl->next; held_list_t *buf = hl->next;
...@@ -1549,5 +1584,6 @@ static void held_objects_destroy (void *data) ...@@ -1549,5 +1584,6 @@ static void held_objects_destroy (void *data)
free (hl); free (hl);
hl = buf; hl = buf;
} }
vlc_restorecancel (canc);
} }
#endif #endif
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