fix a crash caused by calling inner_widget_notifier's destroy twice

This commit is contained in:
Jinhao 2015-08-27 01:40:18 +08:00
parent 29ab6be21b
commit 9384baace4
4 changed files with 17 additions and 13 deletions

View File

@ -31,7 +31,7 @@ namespace nana
: nana::noncopyable, nana::nonmovable : nana::noncopyable, nana::nonmovable
{ {
friend class detail::widget_notifier_interface; friend class detail::widget_notifier_interface;
class notifier; class inner_widget_notifier;
typedef void(*dummy_bool_type)(widget* (*)(const widget&)); typedef void(*dummy_bool_type)(widget* (*)(const widget&));
public: public:
virtual ~widget() = default; virtual ~widget() = default;

View File

@ -326,6 +326,9 @@ namespace detail
std::lock_guard<decltype(mutex_)> lock(mutex_); std::lock_guard<decltype(mutex_)> lock(mutex_);
if (impl_->wd_register.available(wd) == false) return; if (impl_->wd_register.available(wd) == false) return;
if (wd->flags.destroying)
return;
if(wd->other.category == category::root_tag::value) if(wd->other.category == category::root_tag::value)
{ {
auto &brock = bedrock::instance(); auto &brock = bedrock::instance();
@ -340,13 +343,15 @@ namespace detail
if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active) if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active)
native_interface::activate_owner(wd->root); native_interface::activate_owner(wd->root);
if (!wd->flags.destroying)
{
//Close should detach the drawer and send destroy signal to widget object. //Close should detach the drawer and send destroy signal to widget object.
//Otherwise, when a widget object is been deleting in other thread by delete operator, the object will be destroyed //Otherwise, when a widget object is been deleting in other thread by delete operator, the object will be destroyed
//before the window_manager destroyes the window, and then, window_manager detaches the //before the window_manager destroyes the window, and then, window_manager detaches the
//non-existing drawer_trigger which is destroyed by destruction of widget. Crash! //non-existing drawer_trigger which is destroyed by destruction of widget. Crash!
wd->drawer.detached(); wd->drawer.detached();
wd->widget_notifier->destroy(); wd->widget_notifier->destroy();
}
native_interface::close_window(wd->root); native_interface::close_window(wd->root);
} }

View File

@ -1440,7 +1440,6 @@ namespace nana
private: private:
void _m_calc_metrics(graph_reference graph, std::forward_list<item>& items) void _m_calc_metrics(graph_reference graph, std::forward_list<item>& items)
{ {
const auto height_px = graph.height();
std::vector<unsigned> pxs; std::vector<unsigned> pxs;
unsigned pixels = 0; unsigned pixels = 0;

View File

@ -22,10 +22,10 @@ namespace nana
//class widget //class widget
//@brief:The definition of class widget //@brief:The definition of class widget
class widget::notifier: public detail::widget_notifier_interface class widget::inner_widget_notifier : public detail::widget_notifier_interface
{ {
public: public:
notifier(widget& wdg) inner_widget_notifier(widget& wdg)
: wdg_(wdg) : wdg_(wdg)
{} {}
@ -246,7 +246,7 @@ namespace nana
std::unique_ptr<::nana::detail::widget_notifier_interface> widget::_m_wdg_notifier() std::unique_ptr<::nana::detail::widget_notifier_interface> widget::_m_wdg_notifier()
{ {
return std::unique_ptr<::nana::detail::widget_notifier_interface>(new notifier(*this)); return std::unique_ptr<::nana::detail::widget_notifier_interface>(new inner_widget_notifier(*this));
} }
void widget::_m_complete_creation() void widget::_m_complete_creation()
@ -348,7 +348,7 @@ namespace nana
{ {
std::unique_ptr<widget_notifier_interface> widget_notifier_interface::get_notifier(widget* wdg) std::unique_ptr<widget_notifier_interface> widget_notifier_interface::get_notifier(widget* wdg)
{ {
return std::unique_ptr<widget_notifier_interface>(new widget::notifier(*wdg)); return std::unique_ptr<widget_notifier_interface>(new widget::inner_widget_notifier(*wdg));
} }
} }
}//end namespace nana }//end namespace nana