[gnote] Fix a race condition causing a crash (Closes #584183)



commit c5cd8d339699ff6bfa29fd111d569f9999213bfe
Author: Hubert Figuiere <hub figuiere net>
Date:   Thu Jun 4 20:39:22 2009 -0400

    Fix a race condition causing a crash (Closes #584183)
---
 NEWS                                      |    1 +
 src/addins/bugzilla/bugzillanoteaddin.cpp |    1 -
 src/addins/bugzilla/insertbugaction.cpp   |    5 +-
 src/addins/bugzilla/insertbugaction.hpp   |    5 +-
 src/note.cpp                              |    4 +-
 src/notebuffer.cpp                        |    4 +-
 src/notebuffer.hpp                        |    8 ++-
 src/notetag.cpp                           |    2 +-
 src/notetag.hpp                           |    8 ++--
 src/undo.cpp                              |   78 +++++++++++++++--------------
 src/undo.hpp                              |   42 +++++++++-------
 11 files changed, 84 insertions(+), 74 deletions(-)

diff --git a/NEWS b/NEWS
index 0bc33d6..af730f2 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Fixes:
 
   * Remove libxml++. (Closes #579292) Possibly closes bug #579316.
   * Some code cleanups.
+  * Fix a race condition causing a crash (Closes #584183)
 
 Translations:
 
diff --git a/src/addins/bugzilla/bugzillanoteaddin.cpp b/src/addins/bugzilla/bugzillanoteaddin.cpp
index c475368..8d792d3 100644
--- a/src/addins/bugzilla/bugzillanoteaddin.cpp
+++ b/src/addins/bugzilla/bugzillanoteaddin.cpp
@@ -163,7 +163,6 @@ namespace bugzilla {
       std::string string_id = boost::lexical_cast<std::string>(id);
       buffer->undoer().add_undo_action (new InsertBugAction (cursor, 
                                                              string_id, 
-                                                             buffer,
                                                              link_tag));
 
       std::vector<Glib::RefPtr<Gtk::TextTag> > tags;
diff --git a/src/addins/bugzilla/insertbugaction.cpp b/src/addins/bugzilla/insertbugaction.cpp
index 6fad6af..c510ec7 100644
--- a/src/addins/bugzilla/insertbugaction.cpp
+++ b/src/addins/bugzilla/insertbugaction.cpp
@@ -27,7 +27,6 @@ using gnote::InsertAction;
 namespace bugzilla {
 
   InsertBugAction::InsertBugAction(const Gtk::TextIter & start, const std::string & id,
-                                   const Glib::RefPtr<Gtk::TextBuffer> &,
                                    const BugzillaLink::Ptr & tag)
     : m_tag(tag)
     , m_offset(start.get_offset())
@@ -36,7 +35,7 @@ namespace bugzilla {
     
   }
 
-  void InsertBugAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertBugAction::undo (Gtk::TextBuffer * buffer)
   {
     // Tag images change the offset by one, but only when deleting.
     Gtk::TextIter start_iter = buffer->get_iter_at_offset(m_offset);
@@ -51,7 +50,7 @@ namespace bugzilla {
   }
 
 
-  void InsertBugAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertBugAction::redo (Gtk::TextBuffer * buffer)
   {
     remove_split_tags (buffer);
 
diff --git a/src/addins/bugzilla/insertbugaction.hpp b/src/addins/bugzilla/insertbugaction.hpp
index 8689247..60fe0a8 100644
--- a/src/addins/bugzilla/insertbugaction.hpp
+++ b/src/addins/bugzilla/insertbugaction.hpp
@@ -33,10 +33,9 @@ class InsertBugAction
 {
 public:
   InsertBugAction(const Gtk::TextIter & start, const std::string & id,
-                  const Glib::RefPtr<Gtk::TextBuffer> & buffer,
                   const BugzillaLink::Ptr & tag);
-  void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  void undo (Gtk::TextBuffer * buffer);
+  void redo (Gtk::TextBuffer * buffer);
   void merge (EditAction * action);
   bool can_merge (const EditAction * action) const;
   void destroy ();
diff --git a/src/note.cpp b/src/note.cpp
index 4595bf5..43764b0 100644
--- a/src/note.cpp
+++ b/src/note.cpp
@@ -955,7 +955,7 @@ namespace gnote {
       // NOTE: Sharing the same TagTable means
       // that formatting is duplicated between
       // buffers.
-      m_tag_table = NoteTagTable::Ptr(&NoteTagTable::instance());
+      m_tag_table = NoteTagTable::instance();
     }
     return m_tag_table;
   }
@@ -964,7 +964,7 @@ namespace gnote {
   {
     if(!m_buffer) {
       DBG_OUT("Creating buffer for %s", m_data.data().title().c_str());
-      m_buffer = Glib::RefPtr<NoteBuffer>(new NoteBuffer(get_tag_table(), *this));
+      m_buffer = NoteBuffer::create(get_tag_table(), *this);
       m_data.set_buffer(m_buffer);
 
       m_buffer->signal_changed().connect(
diff --git a/src/notebuffer.cpp b/src/notebuffer.cpp
index e145d2e..d619bb3 100644
--- a/src/notebuffer.cpp
+++ b/src/notebuffer.cpp
@@ -47,10 +47,10 @@ namespace gnote {
 
   NoteBuffer::NoteBuffer(const NoteTagTable::Ptr & tags, Note & note)
     : Gtk::TextBuffer(tags)
-    , m_undomanager(new UndoManager(Ptr(this)))
+    , m_undomanager(NULL)
     , m_note(note)
   {
-    
+    m_undomanager = new UndoManager(this);
     signal_insert().connect(sigc::mem_fun(*this, &NoteBuffer::text_insert_event));
     signal_erase().connect(sigc::mem_fun(*this, &NoteBuffer::range_deleted_event));
     signal_mark_set().connect(sigc::mem_fun(*this, &NoteBuffer::mark_set_event));
diff --git a/src/notebuffer.hpp b/src/notebuffer.hpp
index f4282f2..10453a1 100644
--- a/src/notebuffer.hpp
+++ b/src/notebuffer.hpp
@@ -41,7 +41,6 @@ namespace sharp {
 
 namespace gnote {
 
-  class NoteTagTable;
   class Note;
   class UndoManager;
 
@@ -55,7 +54,10 @@ public:
   typedef sigc::signal<void, int, bool> ChangeDepthHandler;
 
   bool get_enable_auto_bulleted_lists() const;
-  NoteBuffer(const NoteTagTable::Ptr &, Note &);
+  static Ptr create(const NoteTagTable::Ptr & table, Note & note)
+    {
+      return Ptr(new NoteBuffer(table, note));
+    }
   ~NoteBuffer();
 
   // Signal that text has been inserted, and any active tags have
@@ -107,6 +109,8 @@ public:
   DepthNoteTag::Ptr find_depth_tag(Gtk::TextIter &);
 
 protected: 
+  NoteBuffer(const NoteTagTable::Ptr &, Note &);
+
   virtual void on_apply_tag(const Glib::RefPtr<Gtk::TextTag> & tag,
                        const Gtk::TextIter &,  const Gtk::TextIter &);
   virtual void on_remove_tag(const Glib::RefPtr<Gtk::TextTag> & tag,
diff --git a/src/notetag.cpp b/src/notetag.cpp
index 3db4007..46eea2c 100644
--- a/src/notetag.cpp
+++ b/src/notetag.cpp
@@ -360,7 +360,7 @@ namespace gnote {
   }
 
 
-  NoteTagTable *NoteTagTable::s_instance = NULL;
+  NoteTagTable::Ptr NoteTagTable::s_instance;
 
   void NoteTagTable::_init_common_tags()
   {
diff --git a/src/notetag.hpp b/src/notetag.hpp
index 5321c5c..f2022ea 100644
--- a/src/notetag.hpp
+++ b/src/notetag.hpp
@@ -254,12 +254,12 @@ public:
   typedef Glib::RefPtr<NoteTagTable> Ptr;
   typedef sigc::slot<DynamicNoteTag::Ptr> Factory;
 
-  static NoteTagTable & instance() 
+  static const NoteTagTable::Ptr & instance() 
     {
       if(!s_instance) {
-        s_instance = new NoteTagTable;
+        s_instance = NoteTagTable::Ptr(new NoteTagTable);
       }
-      return *s_instance;
+      return s_instance;
     }
   static bool tag_is_serializable(const Glib::RefPtr<const Gtk::TextTag> & );
   static bool tag_is_growable(const Glib::RefPtr<Gtk::TextTag> & );
@@ -285,7 +285,7 @@ protected:
 private:
   void _init_common_tags();
 
-  static NoteTagTable                   *s_instance;
+  static NoteTagTable::Ptr           s_instance;
   std::map<std::string, Factory>     m_tag_types;
   std::list<Glib::RefPtr<Gtk::TextTag> > m_added_tags;
 };
diff --git a/src/undo.cpp b/src/undo.cpp
index c3ce073..22bb6f0 100644
--- a/src/undo.cpp
+++ b/src/undo.cpp
@@ -52,7 +52,7 @@ namespace gnote {
   }
 
   void SplitterAction::split(Gtk::TextIter iter, 
-                             const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+                             Gtk::TextBuffer * buffer)
   {
     Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> > tag_list = iter.get_tags();
     for(Glib::SListHandle<Glib::RefPtr<Gtk::TextTag> >::const_iterator tag_iter = tag_list.begin();
@@ -109,7 +109,7 @@ namespace gnote {
   }
 
 
-  void SplitterAction::apply_split_tag(const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void SplitterAction::apply_split_tag(Gtk::TextBuffer * buffer)
   {
     for(std::list<TagData>::const_iterator iter = m_splitTags.begin();
         iter != m_splitTags.end(); ++iter) {
@@ -123,7 +123,7 @@ namespace gnote {
   }
 
 
-  void SplitterAction::remove_split_tags(const Glib::RefPtr<Gtk::TextBuffer> &buffer)
+  void SplitterAction::remove_split_tags(Gtk::TextBuffer *buffer)
   {
     for(std::list<TagData>::const_iterator iter = m_splitTags.begin();
         iter != m_splitTags.end(); ++iter) {
@@ -147,7 +147,7 @@ namespace gnote {
   }
 
 
-  void InsertAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertAction::undo (Gtk::TextBuffer * buffer)
   {
     int tag_images = get_split_offset ();
 
@@ -164,7 +164,7 @@ namespace gnote {
   }
 
 
-  void InsertAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertAction::redo (Gtk::TextBuffer * buffer)
   {
     remove_split_tags (buffer);
 
@@ -244,7 +244,7 @@ namespace gnote {
   }
 
 
-  void EraseAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void EraseAction::undo (Gtk::TextBuffer * buffer)
   {
     int tag_images = get_split_offset ();
 
@@ -262,7 +262,7 @@ namespace gnote {
   }
 
 
-  void EraseAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void EraseAction::redo (Gtk::TextBuffer * buffer)
   {
     remove_split_tags (buffer);
 
@@ -360,7 +360,7 @@ namespace gnote {
   }
 
 
-  void TagApplyAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void TagApplyAction::undo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter start_iter, end_iter;
     start_iter = buffer->get_iter_at_offset (m_start);
@@ -372,7 +372,7 @@ namespace gnote {
   }
 
 
-  void TagApplyAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void TagApplyAction::redo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter start_iter, end_iter;
     start_iter = buffer->get_iter_at_offset (m_start);
@@ -411,7 +411,7 @@ namespace gnote {
   }
 
 
-  void TagRemoveAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void TagRemoveAction::undo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter start_iter, end_iter;
     start_iter = buffer->get_iter_at_offset (m_start);
@@ -423,7 +423,7 @@ namespace gnote {
   }
 
 
-  void TagRemoveAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void TagRemoveAction::redo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter start_iter, end_iter;
     start_iter = buffer->get_iter_at_offset (m_start);
@@ -459,37 +459,41 @@ namespace gnote {
   }
 
 
-  void ChangeDepthAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void ChangeDepthAction::undo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter iter = buffer->get_iter_at_line (m_line);
 
-    NoteBuffer::Ptr note_buffer = NoteBuffer::Ptr::cast_dynamic(buffer);
-    if (m_direction) {
-      note_buffer->decrease_depth (iter);
-    }
-    else {
-      note_buffer->increase_depth (iter);
-    }
+    NoteBuffer* note_buffer = dynamic_cast<NoteBuffer*>(buffer);
+    if(note_buffer) {
+      if (m_direction) {
+        note_buffer->decrease_depth (iter);
+      }
+      else {
+        note_buffer->increase_depth (iter);
+      }
 
-    buffer->move_mark (buffer->get_insert(), iter);
-    buffer->move_mark (buffer->get_selection_bound(), iter);
+      buffer->move_mark (buffer->get_insert(), iter);
+      buffer->move_mark (buffer->get_selection_bound(), iter);
+    }
   }
 
 
-  void ChangeDepthAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void ChangeDepthAction::redo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter iter = buffer->get_iter_at_line (m_line);
 
-    NoteBuffer::Ptr note_buffer = NoteBuffer::Ptr::cast_dynamic(buffer);
-    if (m_direction) {
-      note_buffer->increase_depth (iter);
-    } 
-    else {
-      note_buffer->decrease_depth (iter);
-    }
+    NoteBuffer* note_buffer = dynamic_cast<NoteBuffer*>(buffer);
+    if(note_buffer) {    
+      if (m_direction) {
+        note_buffer->increase_depth (iter);
+      } 
+      else {
+        note_buffer->decrease_depth (iter);
+      }
 
-    buffer->move_mark (buffer->get_insert(), iter);
-    buffer->move_mark (buffer->get_selection_bound(), iter);
+      buffer->move_mark (buffer->get_insert(), iter);
+      buffer->move_mark (buffer->get_selection_bound(), iter);
+    }
   }
 
 
@@ -520,13 +524,13 @@ namespace gnote {
   }
 
 
-  void InsertBulletAction::undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertBulletAction::undo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter iter = buffer->get_iter_at_offset (m_offset);
     iter.forward_line ();
     iter = buffer->get_iter_at_line (iter.get_line());
 
-    NoteBuffer::Ptr::cast_dynamic(buffer)->remove_bullet (iter);
+    dynamic_cast<NoteBuffer*>(buffer)->remove_bullet (iter);
 
     iter.forward_to_line_end ();
 
@@ -535,14 +539,14 @@ namespace gnote {
   }
 
 
-  void InsertBulletAction::redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer)
+  void InsertBulletAction::redo (Gtk::TextBuffer * buffer)
   {
     Gtk::TextIter iter = buffer->get_iter_at_offset (m_offset);
 
     buffer->insert (iter, "\n");
 
-    NoteBuffer::Ptr::cast_dynamic(buffer)->insert_bullet (iter, 
-                                                          m_depth, m_direction);
+    dynamic_cast<NoteBuffer*>(buffer)->insert_bullet (iter, 
+                                                      m_depth, m_direction);
 
     buffer->move_mark (buffer->get_insert(), iter);
     buffer->move_mark (buffer->get_selection_bound(), iter);
@@ -566,7 +570,7 @@ namespace gnote {
   }
   
 
-  UndoManager::UndoManager(const NoteBuffer::Ptr & buffer)
+  UndoManager::UndoManager(NoteBuffer * buffer)
     : m_frozen_cnt(0)
     , m_try_merge(false)
     , m_buffer(buffer)
diff --git a/src/undo.hpp b/src/undo.hpp
index 5dd7dc6..f44f539 100644
--- a/src/undo.hpp
+++ b/src/undo.hpp
@@ -42,8 +42,8 @@ namespace gnote {
 class EditAction
 {
 public:
-  virtual  void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer) = 0;
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer) = 0;
+  virtual  void undo (Gtk::TextBuffer * buffer) = 0;
+  virtual void redo (Gtk::TextBuffer * buffer) = 0;
   virtual void merge (EditAction * action) = 0;
   virtual bool can_merge (const EditAction * action) const = 0;
   virtual void destroy () = 0;
@@ -77,14 +77,14 @@ public:
     {
       return m_splitTags;
     }
-  void split(Gtk::TextIter iter, const Glib::RefPtr<Gtk::TextBuffer> &);
+  void split(Gtk::TextIter iter, Gtk::TextBuffer *);
   void add_split_tag(const Gtk::TextIter &, const Gtk::TextIter &, 
                      const Glib::RefPtr<Gtk::TextTag> tag);
 protected:
   SplitterAction();
   int get_split_offset() const;
-  void apply_split_tag(const Glib::RefPtr<Gtk::TextBuffer> &);
-  void remove_split_tags(const Glib::RefPtr<Gtk::TextBuffer> &);
+  void apply_split_tag(Gtk::TextBuffer *);
+  void remove_split_tags(Gtk::TextBuffer *);
   std::list<TagData> m_splitTags;
   utils::TextRange   m_chop;
 };
@@ -97,8 +97,8 @@ class InsertAction
 public:
   InsertAction(const Gtk::TextIter & start, const std::string & text, int length,
                const ChopBuffer::Ptr & chop_buf);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -115,8 +115,8 @@ class EraseAction
 public:
   EraseAction(const Gtk::TextIter & start_iter, const Gtk::TextIter & end_iter,
                const ChopBuffer::Ptr & chop_buf);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -135,8 +135,8 @@ class TagApplyAction
 {
 public:
   TagApplyAction(const Glib::RefPtr<Gtk::TextTag> &, const Gtk::TextIter & start, const Gtk::TextIter & end);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -153,8 +153,8 @@ class TagRemoveAction
 {
 public:
   TagRemoveAction(const Glib::RefPtr<Gtk::TextTag> &, const Gtk::TextIter & start, const Gtk::TextIter & end);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -170,8 +170,8 @@ class ChangeDepthAction
 {
 public:
   ChangeDepthAction(int line, bool direction);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -187,8 +187,8 @@ class InsertBulletAction
 {
 public:
   InsertBulletAction(int offset, int depth, Pango::Direction direction);
-  virtual void undo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
-  virtual void redo (const Glib::RefPtr<Gtk::TextBuffer> & buffer);
+  virtual void undo (Gtk::TextBuffer * buffer);
+  virtual void redo (Gtk::TextBuffer * buffer);
   virtual void merge (EditAction * action);
   virtual bool can_merge (const EditAction * action) const;
   virtual void destroy ();
@@ -202,7 +202,11 @@ class UndoManager
   : public boost::noncopyable
 {
 public:
-  UndoManager(const NoteBuffer::Ptr & buffer);
+  /** the buffer it NOT owned by the UndoManager
+   *  it is assume to have a longer life than UndoManager
+   *  Actually the UndoManager belong to the buffer.
+   */
+  UndoManager(NoteBuffer * buffer);
   ~UndoManager();
   bool get_can_undo()
     {
@@ -251,7 +255,7 @@ private:
 
   guint m_frozen_cnt;
   bool m_try_merge;
-  NoteBuffer::Ptr m_buffer;
+  NoteBuffer * m_buffer;
   ChopBuffer::Ptr m_chop_buffer;
   std::stack<EditAction *> m_undo_stack;
   std::stack<EditAction *> m_redo_stack;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]