Re: [sigc] sigc slot & shared_ptr anti-pattern



On Aug 24, 2006, at 9:46 AM, Paul Davis wrote:
below is a tiny program that demonstrates either an anti-pattern or a
bug or both in the use/design of libsigc++. the program will generally
run normally, but using valgrind reveals something deeply wrong, as
noted in the annotations in the code.

the basic rule seems to be that you must never, ever put a shared_ptr<T>
into a slot if:

	1) T has a sigc::signal
	2) the slot could end up being the last instance of shared_ptr<T> to
this particular "T"

keep in mind that the lifetime of "b" in the example is artificially
short. all that really matters is that b's lifetime would have ended
before that of a if it was not referenced by a shared_ptr in a slot
belonging to a.

comments welcome.

I've banged my head on this problem myself. It isn't a bug in shared_ptr IMHO; I experienced the problem with my own custom-rolled smart pointers.

Basically, if a signal object is destroyed as a result of a slot being disconnected from it, libsigc++'s basic checks to make sure it doesn't double-delete are bypassed. In the process of disconnecting from the slot end, the slot is partially torn down. It then releases its internal stuff, which destroys the signal. The signal tries to disconnect all slots, but this slot is still "in-process" of being destroyed. It's fully destroyed by the signal, but the slot-end thinks that it still needs to perform a final delete to finish cleaning up the slot. Voila, double-delete.

When I spent a fair amount of time tracing through the relevant code and backtraces, I (unfortunately) didn't see a good way to rectify this situation; libsigc++ seems to make all sensible checks. It becomes a problem because (IIRC) slot_rep is deleted from the signal end as a result of the invocation of a slot_rep method, and that method tries to do one more cleanup action after the line that results in the deletion occurs. Result: there's a method still running though its object has been deleted, and it blows up.

My conclusion walking away from the matter was that the best solution is just to avoid storing reference-counting pointers in slots; using a bald pointer or weak pointer is a better option. This should probably be documented somewhere, though.

- Michael



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