]> git.tdb.fi Git - r2c2.git/commitdiff
Avoid segfault if an exception is thrown while loading
authorMikko Rasa <tdb@tdb.fi>
Wed, 7 May 2014 20:26:13 +0000 (23:26 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 8 May 2014 15:27:03 +0000 (18:27 +0300)
The Layout::add functions are called from object constructors.  If an
exception is thrown inside them, the constructor will abort and the
object will be deleted.  If that happens, it must be removed from the
Layout as well, or an invalid memory access will occur later.

source/libr2c2/layout.cpp

index 0901382b91d0f140bb8ddf39010bf41228b33bfb..af7304da6aeef557f3f4f8119d08cc4aaca1ace4 100644 (file)
@@ -69,31 +69,69 @@ Driver &Layout::get_driver() const
 void Layout::add(Object &o)
 {
        if(objects.insert(o))
-               signal_object_added.emit(o);
+       {
+               try
+               {
+                       signal_object_added.emit(o);
+               }
+               catch(...)
+               {
+                       objects.erase(o);
+                       throw;
+               }
+       }
 }
 
 void Layout::add(Track &t)
 {
        if(objects.insert(t))
        {
-               // Blocks must be recreated first
-               create_blocks();
-               signal_object_added.emit(t);
+               try
+               {
+                       // Blocks must be recreated first
+                       create_blocks();
+                       signal_object_added.emit(t);
+               }
+               catch(...)
+               {
+                       objects.erase(t);
+                       create_blocks();
+                       throw;
+               }
        }
 }
 
 void Layout::add(TrackChain &g)
 {
        if(track_chains.insert(g))
-               signal_track_chain_added.emit(g);
+       {
+               try
+               {
+                       signal_track_chain_added.emit(g);
+               }
+               catch(...)
+               {
+                       track_chains.erase(g);
+                       throw;
+               }
+       }
 }
 
 void Layout::add(Block &b)
 {
        if(track_chains.insert(b))
        {
-               b.signal_reserved.connect(sigc::bind<0>(signal_block_reserved, sigc::ref(b)));
-               signal_track_chain_added.emit(b);
+               sigc::connection conn = b.signal_reserved.connect(sigc::bind<0>(signal_block_reserved, sigc::ref(b)));
+               try
+               {
+                       signal_track_chain_added.emit(b);
+               }
+               catch(...)
+               {
+                       track_chains.erase(b);
+                       conn.disconnect();
+                       throw;
+               }
        }
 }