Changeset 2164

Show
Ignore:
Timestamp:
06/12/12 06:11:28 (8 years ago)
Author:
jwoithe
Message:

A more robust solution to ticket #354. Rather than relying on an ad hoc delay, use a condition variable to ensure that PosixThread::ThreadHandler?() acquires m_lock before anything else. It is particularly important that PosixThread::Kill() and PosixThread::Stop() don't lock m_lock before PosixThread::ThreadHandler?(); otherwise a deadlock will result.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/src/libieee1394/ieee1394service.cpp

    r2162 r2164  
    403403        return false; 
    404404    } 
    405  
    406     // Give time for all threads to start.  Otherwise it can happen that 
    407     // some FFADO threads are ready to run before others.  If the former 
    408     // then go ahead and use the latter on the assumption that they're 
    409     // running, race conditions can occur.  The delay here has been  
    410     // determined experimentally. 
    411     usleep(500); 
    412405 
    413406    // make sure that the thread parameters of all our helper threads are OK 
  • trunk/libffado/src/libutil/PosixThread.cpp

    r1971 r2164  
    6767    obj->m_lock.Lock(); 
    6868 
     69    // Signal that ThreadHandler has acquired its initial lock 
     70    pthread_mutex_lock(&obj->handler_active_lock); 
     71    obj->handler_active = 1; 
     72    pthread_cond_signal(&obj->handler_active_cond); 
     73    pthread_mutex_unlock(&obj->handler_active_lock); 
     74 
    6975    if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) { 
    7076        debugError("pthread_setcanceltype err = %s\n", strerror(err)); 
     
    7480    if (!runnable->Init()) { 
    7581        debugError("Thread init fails: thread quits\n"); 
     82        obj->m_lock.Unlock(); 
    7683        return 0; 
    7784    } 
     
    156163            return -1; 
    157164        } 
    158  
    159         return 0; 
    160165    } else { 
    161166        debugOutput( DEBUG_LEVEL_VERBOSE, "(%s) Create non RT thread %p\n", m_id.c_str(), this); 
     
    168173            return -1; 
    169174        } 
    170  
    171         return 0; 
    172     } 
     175    } 
     176 
     177    // Wait for ThreadHandler() to acquire the thread lock (m_lock) before 
     178    // continuing, thereby ensuring that ThreadHandler() acquires a lock on 
     179    // m_lock before anything else tries. 
     180    pthread_mutex_lock(&handler_active_lock); 
     181    while (handler_active == 0) 
     182        pthread_cond_wait(&handler_active_cond, &handler_active_lock); 
     183    pthread_mutex_unlock(&handler_active_lock); 
     184 
     185    return 0; 
    173186} 
    174187 
  • trunk/libffado/src/libutil/PosixThread.h

    r1550 r2164  
    7474        int fCancellation; 
    7575 
     76        pthread_mutex_t handler_active_lock; 
     77        pthread_cond_t handler_active_cond; 
     78        int handler_active; 
     79 
    7680        static void* ThreadHandler(void* arg); 
    7781        Util::Mutex &m_lock; 
     
    8084        PosixThread(RunnableInterface* runnable, bool real_time, int priority, int cancellation) 
    8185                : Thread(runnable), fThread((pthread_t)NULL), fPriority(priority), fRealTime(real_time), fRunning(false), fCancellation(cancellation) 
     86                , handler_active(0) 
    8287                , m_lock(*(new Util::PosixMutex("THREAD"))) 
    83         {} 
     88        { pthread_mutex_init(&handler_active_lock, NULL);  
     89          pthread_cond_init(&handler_active_cond, NULL); 
     90        } 
    8491        PosixThread(RunnableInterface* runnable) 
    8592                : Thread(runnable), fThread((pthread_t)NULL), fPriority(0), fRealTime(false), fRunning(false), fCancellation(PTHREAD_CANCEL_DEFERRED) 
     93                , handler_active(0) 
    8694                , m_lock(*(new Util::PosixMutex("THREAD"))) 
    87         {} 
     95        { pthread_mutex_init(&handler_active_lock, NULL);  
     96          pthread_cond_init(&handler_active_cond, NULL); 
     97        } 
    8898        PosixThread(RunnableInterface* runnable, int cancellation) 
    8999                : Thread(runnable), fThread((pthread_t)NULL), fPriority(0), fRealTime(false), fRunning(false), fCancellation(cancellation) 
     100                , handler_active(0) 
    90101                , m_lock(*(new Util::PosixMutex("THREAD"))) 
    91         {} 
     102        { pthread_mutex_init(&handler_active_lock, NULL);  
     103          pthread_cond_init(&handler_active_cond, NULL); 
     104        } 
    92105 
    93106        PosixThread(RunnableInterface* runnable, std::string id, bool real_time, int priority, int cancellation) 
    94107                : Thread(runnable, id), fThread((pthread_t)NULL), fPriority(priority), fRealTime(real_time), fRunning(false), fCancellation(cancellation) 
     108                , handler_active(0) 
    95109                , m_lock(*(new Util::PosixMutex(id))) 
    96         {} 
     110        { pthread_mutex_init(&handler_active_lock, NULL);  
     111          pthread_cond_init(&handler_active_cond, NULL); 
     112        } 
    97113        PosixThread(RunnableInterface* runnable, std::string id) 
    98114                : Thread(runnable, id), fThread((pthread_t)NULL), fPriority(0), fRealTime(false), fRunning(false), fCancellation(PTHREAD_CANCEL_DEFERRED) 
     115                , handler_active(0) 
    99116                , m_lock(*(new Util::PosixMutex(id))) 
    100         {} 
     117        { pthread_mutex_init(&handler_active_lock, NULL);  
     118          pthread_cond_init(&handler_active_cond, NULL); 
     119        } 
    101120        PosixThread(RunnableInterface* runnable, std::string id, int cancellation) 
    102121                : Thread(runnable, id), fThread((pthread_t)NULL), fPriority(0), fRealTime(false), fRunning(false), fCancellation(cancellation) 
     122                , handler_active(0) 
    103123                , m_lock(*(new Util::PosixMutex(id))) 
    104         {} 
     124        { pthread_mutex_init(&handler_active_lock, NULL);  
     125          pthread_cond_init(&handler_active_cond, NULL); 
     126        } 
    105127 
    106128        virtual ~PosixThread() 
    107         { delete &m_lock; } 
     129        { delete &m_lock;  
     130          pthread_mutex_destroy(&handler_active_lock);  
     131          pthread_cond_destroy(&handler_active_cond); 
     132        } 
    108133 
    109134        virtual int Start();