Changeset 689dd889dee2ea43e8a7cb64ccec0b923a8a60bd

Show
Ignore:
Timestamp:
28/01/08 18:01:48 (9 months ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1201539708 +0000
git-parent:

[e15891a3316a7b2c3fc0480fd5ff8f18858d8802]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1201539708 +0000
Message:

Only use waitpipe for _kill, rather than _signal, which is what people expect
(You really don't usually want your net_Read/net_Write to interrupted).
In the process, fix a deadlock in vlc_cond_wait() when waitpipe is used - fixes #1448

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/libvlc.h

    rd9b5111 r689dd88  
    110110 
    111111    /* Objects thread synchronization */ 
    112     vlc_bool_t      b_signaled; 
    113112    int             pipes[2]; 
    114113    vlc_spinlock_t  spin; 
  • src/misc/objects.c

    rb941c1e r689dd88  
    451451    vlc_cond_destroy( &p_this->object_wait ); 
    452452    vlc_spin_destroy( &p_priv->spin ); 
     453    if( p_priv->pipes[1] != -1 ) 
     454        close( p_priv->pipes[1] ); 
    453455    if( p_priv->pipes[0] != -1 ) 
    454456        close( p_priv->pipes[0] ); 
    455     if( p_priv->pipes[1] != -1 ) 
    456         close( p_priv->pipes[1] ); 
    457457 
    458458    /* global is not dynamically allocated by vlc_object_create */ 
     
    529529 
    530530/** 
    531  * Returns the readable end of a pipe that becomes readable whenever 
    532  * an object is signaled. This can be used to wait for VLC object events 
    533  * inside select(), poll() loops or frameworks providing an event loop. 
     531 * Returns the readable end of a pipe that becomes readable once termination 
     532 * of the object is requested (vlc_object_kill()). 
     533 * This can be used to wake-up out of a select() or poll() event loop, such 
     534 * typically when doing network I/O. 
    534535 * 
    535536 * Note that the pipe will remain the same for the lifetime of the object. 
    536  * DO NOT close it yourself. Ever. 
     537 * DO NOT read the pipe nor close it yourself. Ever. 
    537538 * 
    538  * DO NOT try to read from the pipe either: call vlc_object_wait() instead. 
    539  * Assuming the pipe is readable, vlc_object_wait() will not block. 
    540  * Also note that, as with vlc_object_wait(), there may be spurious wakeups. 
    541  * 
    542  * @param obj object that would be signaled 
     539 * @param obj object that would be "killed" 
    543540 * @return a readable pipe descriptor, or -1 on error. 
    544541 */ 
     
    547544    int pfd[2] = { -1, -1 }; 
    548545    struct vlc_object_internals_t *internals = obj->p_internals; 
    549     vlc_bool_t race = VLC_FALSE, signaled = VLC_FALSE; 
     546    vlc_bool_t killed = VLC_FALSE; 
    550547 
    551548    vlc_spin_lock (&internals->spin); 
     
    560557 
    561558        vlc_spin_lock (&internals->spin); 
    562         signaled = internals->b_signaled; 
    563559        if (internals->pipes[0] == -1) 
    564560        { 
    565561            internals->pipes[0] = pfd[0]; 
    566562            internals->pipes[1] = pfd[1]; 
    567         } 
    568         else 
    569             race = VLC_TRUE
     563            pfd[0] = pfd[1] = -1; 
     564        } 
     565        killed = obj->b_die
    570566    } 
    571567    vlc_spin_unlock (&internals->spin); 
    572568 
    573     if (race) 
    574     {   /* Race condition: two threads call pipe() - unlikely */ 
     569    if (killed) 
     570    { 
     571        /* Race condition: vlc_object_kill() already invoked! */ 
     572        int fd; 
     573 
     574        vlc_spin_lock (&internals->spin); 
     575        fd = internals->pipes[1]; 
     576        internals->pipes[1] = -1; 
     577        vlc_spin_unlock (&internals->spin); 
     578        if (fd != -1) 
     579            close (fd); 
     580    } 
     581 
     582    /* Race condition: two threads call pipe() - unlikely */ 
     583    if (pfd[0] != -1) 
    575584        close (pfd[0]); 
     585    if (pfd[1] != -1) 
    576586        close (pfd[1]); 
    577     } 
    578  
    579     if (signaled) 
    580         /* Race condition: lc_object_signal() already invoked! */ 
    581         while (write (internals->pipes[1], &(char){ 0 }, 1) < 0); 
    582587 
    583588    return internals->pipes[0]; 
     
    594599vlc_bool_t __vlc_object_wait( vlc_object_t *obj ) 
    595600{ 
    596     int fd; 
    597  
    598601    vlc_assert_locked( &obj->object_lock ); 
    599  
    600     fd = obj->p_internals->pipes[0]; 
    601     if (fd != -1) 
    602     { 
    603         while (read (fd, &(char){ 0 }, 1)  < 0); 
    604         return obj->b_die; 
    605     } 
    606  
    607602    vlc_cond_wait( &obj->object_wait, &obj->object_lock ); 
    608     obj->p_internals->b_signaled = VLC_FALSE; 
    609603    return obj->b_die; 
    610604} 
     
    668662void __vlc_object_signal_unlocked( vlc_object_t *obj ) 
    669663{ 
    670     struct vlc_object_internals_t *internals = obj->p_internals; 
    671     int fd; 
    672  
    673664    vlc_assert_locked (&obj->object_lock); 
    674  
    675     vlc_spin_lock (&internals->spin); 
    676     fd = internals->pipes[1]; 
    677     internals->b_signaled = VLC_TRUE; 
    678     vlc_spin_unlock (&internals->spin); 
    679  
    680     if( fd != -1 ) 
    681         while( write( fd, &(char){ 0 }, 1 ) < 0 ); 
    682  
    683665    vlc_cond_signal( &obj->object_wait ); 
    684666} 
     
    691673void __vlc_object_kill( vlc_object_t *p_this ) 
    692674{ 
     675    struct vlc_object_internals_t *internals = p_this->p_internals; 
     676    int fd; 
     677 
    693678    vlc_mutex_lock( &p_this->object_lock ); 
    694679    p_this->b_die = VLC_TRUE; 
     680 
     681    vlc_spin_lock (&internals->spin); 
     682    fd = internals->pipes[1]; 
     683    internals->pipes[1] = -1; 
     684    vlc_spin_unlock (&internals->spin); 
     685 
     686    if( fd != -1 ) 
     687        close (fd); 
    695688 
    696689    if( p_this->i_object_type == VLC_OBJECT_LIBVLC )