Boost logo

Boost Users :

From: Buddha Buck (blaisepascal_at_[hidden])
Date: 2007-07-11 10:30:31


On 7/10/07, Peter Dimov <pdimov_at_[hidden]> wrote:
> Buddha Buck wrote:
> ...
> > My solution was:
> >
> > template <typename T>
> > class wxObserver : public Observer {
> > private:
> > T* p;
> > wxObserver();
> > public:
> > wxObserver(T* p) : p(p);
> > void update(shared_ptr<Observed> o) { if (p) p->update(o); }
> > }
> >
> > class MyWidget : public wxWidget {
> > private:
> > shared_ptr<wxObserver<MyWidget> > observer;
> > public:
> > MyWidget(...) : wxWidget(...), observer(this) { ...
> > observed->register(observer); ... }
> > ...
> > }
> >
> > The idea is that when a MyWidget is created, it creates a shared
> > pointer to a wxObserver and can register that wxObserver with observed
> > objects without a problem. When wxWidgets chooses to delete the
> > MyWidget, the shared pointer the MyWidget goes away, the wxObserver is
> > deleted, and the weak pointers held by the observed objects expire.
> > The implementation of Observed::notifyObservers() checks to make sure
> > that the observers still exist before update()ing them, and only the
> > live observers are updated.
> >
> > The problem is that sometimes, after wxWidgets destroys a MyWidget,
> > calls to Observed::notifyObservers() crashes with a segfault within
> > the call to i->lock().
>
> I think I see one problem in your code, but it cannot explain a segfault
> within i->lock(). When MyWidget is destroyed, if at the exact same time an
> Observed locks its weak_ptr to the wxObserver, the T* p pointer will dangle.

I can see that, and I don't see an easy solution. I tried modifying
~MyWidget so that it explicitly set the T* p pointer to NULL, but that
didn't change the behavior.

> Can you post a stack trace? The problem you describe sounds like a race
> between notifyObservers and ~Observed or register, is that possible?

A stack trace is below this paragraph. It seems impossible for there
to be a race between anything and ~Observed, since the Observed in
this case (an instance of the ObjectDB class) is a long-lasting object
that shouldn't be deleted until the end of the application.

gdb shows only one thread in the application, which makes race
conditions seem even more unlikely to me.

(One note: my Observed class is really called "Subject", which is why
the trace below includes Subject::notifyObservers() and not
Observed::notifyObservers().

#0 0x000000000041c711 in boost::detail::atomic_conditional_increment
(pw=0x2b3ba59cdae8) at
vendor/include/boost/detail/sp_counted_base_gcc_x86.hpp:92
#1 0x000000000041c743 in boost::detail::sp_counted_base::add_ref_lock
(this=0x2b3ba59cdae0) at
vendor/include/boost/detail/sp_counted_base_gcc_x86.hpp:138
#2 0x000000000041d7a1 in shared_count (this=0x7fff083b7678,
r=@0x70f4a78) at vendor/include/boost/detail/shared_count.hpp:362
#3 0x00002b3ba3bcb6ff in shared_ptr<Observer> (this=0x7fff083b7670,
r=@0x70f4a70) at vendor/include/boost/shared_ptr.hpp:187
#4 0x00002b3ba3bcb745 in boost::weak_ptr<Observer>::lock
(this=0x70f4a70) at vendor/include/boost/weak_ptr.hpp:106
#5 0x00002b3ba3bcac9b in Subject::notifyObservers (this=0x5a91e0) at
src/core/Observer.cpp:40
#6 0x00002b3ba3bc320d in ObjectDB::createObject (this=0x5a91e0,
parent=@0x7fff083b7900, type=@0x7fff083b78f0, label=@0x7fff083b78e0,
_guid=@0x7fff083b78d0) at src/core/ObjectDB.cpp:101

>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net