fix “no per-thread pool” abort
authorRobin Gareus <robin@gareus.org>
Tue, 10 Mar 2015 23:25:10 +0000 (00:25 +0100)
committerRobin Gareus <robin@gareus.org>
Tue, 10 Mar 2015 23:25:10 +0000 (00:25 +0100)
For some backends the process thread can change (e.g.
switch coreaudio headphone + internal speakers)

If there are existing x-thread event calls this can lead to
the following situation:

1) SessionEvent::operator new
2) audioengine process thread change
3) SessionEvent::operator delete  -> crash, wrong thread

SessionEvent::operator delete can safely push the event back to
the pool for later cleanup..

libs/ardour/session_events.cc
libs/pbd/pbd/pool.h
libs/pbd/pool.cc

index 0208c03cb127c1ba3bcfdcb14d36a2b197e1b76d..d41b9c50021169dc1ccabe9529a4524dc374fb67 100644 (file)
@@ -86,7 +86,7 @@ SessionEvent::operator new (size_t)
 void
 SessionEvent::operator delete (void *ptr, size_t /*size*/)
 {
-       Pool* p = pool->per_thread_pool ();
+       Pool* p = pool->per_thread_pool (false);
        SessionEvent* ev = static_cast<SessionEvent*> (ptr);
 
        DEBUG_TRACE (DEBUG::SessionEvents, string_compose (
@@ -100,9 +100,10 @@ SessionEvent::operator delete (void *ptr, size_t /*size*/)
        }
 #endif
 
-       if (p == ev->own_pool) {
+       if (p && p == ev->own_pool) {
                p->release (ptr);
        } else {
+               assert(ev->own_pool);
                ev->own_pool->push (ev);
                DEBUG_TRACE (DEBUG::SessionEvents, string_compose ("%1 was wrong thread for this pool, pushed event onto pending list, will be deleted on next alloc from %2 pool size %3 free %4 used %5 pending %6\n",
                                                                   pthread_name(), ev->own_pool->name(),
index 1c9ac81a3e30f774929d468be508d29f7eba18a9..cfd782a794fa50a029f7cda0968f8b5f48a5d3af 100644 (file)
@@ -128,7 +128,7 @@ class LIBPBD_API PerThreadPool
         const Glib::Threads::Private<CrossThreadPool>& key() const { return _key; }
 
        void  create_per_thread_pool (std::string name, unsigned long item_size, unsigned long nitems);
-       CrossThreadPool* per_thread_pool ();
+       CrossThreadPool* per_thread_pool (bool must_exist = true);
 
        void set_trash (RingBuffer<CrossThreadPool*>* t);
        void add_to_trash (CrossThreadPool *);
index b3e5c52e1aeb0c81a45c59ec50ae5469b9193973..020f296f61bf7e3ea13b63515c792539eb5dc01e 100644 (file)
@@ -179,10 +179,10 @@ PerThreadPool::create_per_thread_pool (string n, unsigned long isize, unsigned l
  *  calling create_per_thread_pool in the current thread.
  */
 CrossThreadPool*
-PerThreadPool::per_thread_pool ()
+PerThreadPool::per_thread_pool (bool must_exist)
 {
        CrossThreadPool* p = _key.get();
-       if (!p) {
+       if (!p && must_exist) {
                fatal << "programming error: no per-thread pool \"" << _name << "\" for thread " << pthread_name() << endmsg;
                abort(); /*NOTREACHED*/
        }