Fix a crash that can occur when destroying a handler object that owns its

own memory (as is the case when destroying handlers in an orphaned strand).
This commit is contained in:
chris_kohlhoff 2008-05-27 00:23:16 +00:00
parent 596e733ed4
commit fb4f83d903
9 changed files with 132 additions and 0 deletions

View File

@ -198,6 +198,15 @@ private:
this_type* h(static_cast<this_type*>(base));
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
handler_ptr<alloc_traits> ptr(h->handler_, h);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(h->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
private:

View File

@ -245,6 +245,15 @@ private:
this_type* h(static_cast<this_type*>(base));
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
handler_ptr<alloc_traits> ptr(h->handler_, h);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(h->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
private:

View File

@ -417,6 +417,15 @@ private:
this_type* this_op(static_cast<this_type*>(base));
typedef handler_alloc_traits<Operation, this_type> alloc_traits;
handler_ptr<alloc_traits> ptr(this_op->operation_, this_op);
// A sub-object of the operation may be the true owner of the memory
// associated with the operation. Consequently, a local copy of the
// operation is required to ensure that any owning sub-object remains
// valid until after we have deallocated the memory here.
Operation operation(this_op->operation_);
// Free the memory associated with the operation.
ptr.reset();
}
private:

View File

@ -340,6 +340,15 @@ public:
this_type* h(static_cast<this_type*>(base));
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
handler_ptr<alloc_traits> ptr(h->handler_, h);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(h->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
private:

View File

@ -306,6 +306,15 @@ private:
this_type* this_timer(static_cast<this_type*>(base));
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(this_timer->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
private:

View File

@ -408,6 +408,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
asio::io_service::work work_;
@ -634,6 +643,15 @@ public:
Handler, op_type> alloc_traits;
asio::detail::handler_ptr<alloc_traits> ptr(
handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
asio::io_service::work work_;

View File

@ -649,6 +649,15 @@ private:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
win_iocp_io_service& io_service_;

View File

@ -801,6 +801,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
asio::io_service::work work_;
@ -1070,6 +1079,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
asio::io_service::work work_;
@ -1329,6 +1347,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
asio::io_service::work work_;
@ -1647,6 +1674,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
endpoint_type& endpoint_;
@ -2001,6 +2037,15 @@ public:
op_type* handler_op(static_cast<op_type*>(op));
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
// A sub-object of the handler may be the true owner of the memory
// associated with the handler. Consequently, a local copy of the handler
// is required to ensure that any owning sub-object remains valid until
// after we have deallocated the memory here.
Handler handler(handler_op->handler_);
// Free the memory associated with the handler.
ptr.reset();
}
win_iocp_io_service& io_service_;

View File

@ -160,6 +160,21 @@ void strand_test()
// The run() calls will not return until all work has finished.
BOOST_CHECK(count == 3);
BOOST_CHECK(exception_count == 2);
count = 0;
ios.reset();
// Check for clean shutdown when handlers posted through an orphaned strand
// are abandoned.
{
strand s2(ios);
s2.post(boost::bind(increment, &count));
s2.post(boost::bind(increment, &count));
s2.post(boost::bind(increment, &count));
}
// No handlers can be called until run() is called.
BOOST_CHECK(count == 0);
}
test_suite* init_unit_test_suite(int, char*[])