Prevent crash in pool destruction during session teardown.
authorCarl Hetherington <carl@carlh.net>
Wed, 14 Apr 2010 23:58:20 +0000 (23:58 +0000)
committerCarl Hetherington <carl@carlh.net>
Wed, 14 Apr 2010 23:58:20 +0000 (23:58 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6905 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/butler.h
libs/ardour/butler.cc
libs/ardour/session.cc
libs/pbd/pbd/pool.h
libs/pbd/pool.cc

index e9e832783beda09e3653df92a87755df57383edc..e3760a8c530d50d2b03ada693b5e8395d0b5a60a 100644 (file)
@@ -49,6 +49,7 @@ class Butler : public SessionHandleRef
        void stop();
        void wait_until_finished();
        bool transport_work_requested() const;
+       void drop_references ();
 
        float read_data_rate() const; ///< in usec
        float write_data_rate() const;
index 8b88197073c10f9d50889dfb5f9f9c6d58364eed..b201960e0e6b5c0b336c03e9afba54f1fce29edc 100644 (file)
@@ -428,5 +428,12 @@ Butler::empty_pool_trash ()
        }
 }
 
+void
+Butler::drop_references ()
+{
+       SessionEvent::pool->set_trash (0);
+}
+
+
 } // namespace ARDOUR
 
index ac8d5d030fe11e4fc81da3f185c728bb2b446850..11832646c886038497652a45782d3675651d43bc 100644 (file)
@@ -229,6 +229,7 @@ Session::destroy ()
 
        Stateful::loading_state_version = 0;
 
+       _butler->drop_references ();
        delete _butler;
        delete midi_control_ui;
 
index 2d6111a4a35d69594a7254d1b1bedb8a51ef97e0..ab06343b4adfa3b649c91f79185f4eddee729603 100644 (file)
@@ -111,10 +111,7 @@ class PerThreadPool
        void  create_per_thread_pool (std::string name, unsigned long item_size, unsigned long nitems);
        CrossThreadPool* per_thread_pool ();
 
-       void set_trash (RingBuffer<CrossThreadPool*>* t) {
-               _trash = t;
-       }
-
+       void set_trash (RingBuffer<CrossThreadPool*>* t);
        void add_to_trash (CrossThreadPool *);
 
   private:
@@ -122,8 +119,10 @@ class PerThreadPool
        std::string _name;
        unsigned long _item_size;
        unsigned long _nitems;
+
+       /** mutex to protect either changes to the _trash variable, or writes to the RingBuffer */
+       Glib::Mutex _trash_mutex;
        RingBuffer<CrossThreadPool*>* _trash;
-       Glib::Mutex _trash_write_mutex;
 };
 
 #endif // __qm_pool_h__
index 7859408c45b73c87965071cecc2dd95a3b1bcc1b..abb8695c23016b56ce26aa781d844f5f5f9ecf1f 100644 (file)
@@ -198,10 +198,19 @@ PerThreadPool::per_thread_pool ()
        return p;
 }
 
+void
+PerThreadPool::set_trash (RingBuffer<CrossThreadPool*>* t)
+{
+       Glib::Mutex::Lock lm (_trash_mutex);
+       _trash = t;
+}
+
 /** Add a CrossThreadPool to our trash, if we have one.  If not, a warning is emitted. */
 void
 PerThreadPool::add_to_trash (CrossThreadPool* p)
 {
+       Glib::Mutex::Lock lm (_trash_mutex);
+       
        if (!_trash) {
                warning << "Pool " << p->name() << " has no trash collector; a memory leak has therefore occurred" << endmsg;
                return;
@@ -211,7 +220,6 @@ PerThreadPool::add_to_trash (CrossThreadPool* p)
           can only be one writer to the _trash RingBuffer)
        */
                
-       Glib::Mutex::Lock lm (_trash_write_mutex);
        _trash->write (&p, 1);
 }