take process lock when adding processors:
authorRobin Gareus <robin@gareus.org>
Sun, 12 Jan 2014 20:47:15 +0000 (21:47 +0100)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 13 Jan 2014 14:39:18 +0000 (09:39 -0500)
fixes possible crash if a processor modifies port-count

1. a processor is inserted and activated with processor-lock held
2. only after that the process_lock() is taken, configure_processors() is called which reconfigures-IO

BUT if the processor that is inserted changes the channel count AND audio is processed before IOs are reconfigured
 -> possible crash (invalid port-buffers)

To reproduce: Bus1 (2in, 3out), Bus2 (2in, 3out)
- add a send from Bus1 to Bus2,
- then add a processor to Bus1, just before the send which
  increases the channel-count to 4 -> occasional crash or assert.

libs/ardour/route.cc

index 4b9285c1c87b19f54a354af013f8e08e133a4710..4171a9b2397cf2abdc45aee5e5e2946544247610 100644 (file)
@@ -947,6 +947,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
        {
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
+               Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
 
                boost::shared_ptr<PluginInsert> pi;
                boost::shared_ptr<PortInsert> porti;
@@ -986,8 +987,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
                // configure redirect ports properly, etc.
 
                {
-                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
                                configure_processors_unlocked (0); // it worked before we tried to add it ...
@@ -1117,6 +1116,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
        {
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
+               Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
 
                for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
 
@@ -1137,8 +1137,8 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                                (*i)->activate ();
                        }
 
+                       /* Think: does this really need to be called for every processor in the loop? */
                        {
-                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                                if (configure_processors_unlocked (err)) {
                                        pstate.restore ();
                                        configure_processors_unlocked (0); // it worked before we tried to add it ...