Fix possible leaks in graph's current design
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Sat, 13 May 2017 00:34:50 +0000 (20:34 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Sun, 28 May 2017 16:57:43 +0000 (12:57 -0400)
commitbd14d76835630e092320c8a04300088242dcdc99
tree7350f2de27b9ee3be5a9be01a3fdb74b4ffa02d2
parent4a6b963eb0e4e9545deacfc74d81d3b9f96f060f
Fix possible leaks in graph's current design

There was a possible leak when, for example:

* The user has a reference to the graph.
* The graph holds its child sink component.
* The sink component has a reference to a notification iterator.
* The notification iterator has a reference to the source component.
* The source component has a reference to its parent, the graph, because
  its reference count is 1 (owned by the notification iterator).

This forms a cycle: sink component owns the notification iterator, which
owns the source component, which owns the graph, which holds the sink
component.

To break this cycle and still guarantee that the lifetime of a
notification iterator's upstream component is equal to or longer than
this iterator's lifetime, we split the notification iterator's
destruction and finalization (user's finalization method) phases. In
other words, a notification iterator can be finalized without being
destroyed. However it is guaranteed that it is always finalized once
destroyed.

A connection keeps a set of created notification iterators (weak
references). There are two possible paths to finalize a notification
iterator:

1. The graph still exists and is not being destroyed, and the final
   reference to the notification iterator is put: the notification
   is destroyed, and since it has not been finalized yet, it's
   finalized during that phase.

2. The graph is being destroyed, and an owner (or more) still owns a
   reference to the notification iterator. The graph's destructor first
   destroys the graph's connections. Each connection finalizes each
   notification iterator in its list, but does not destroy them.
   The notification iterators are marked as finalized. Eventually the
   graph destroys its components, some of which could put the last
   reference to a notification iterator: the notification iterator is
   destroyed, but not finalized twice.

When a notification iterator is marked as finalized, calling its "next"
method returns the new BT_NOTIFICATION_ITERATOR_STATUS_CANCELED status
when its queue is empty (instead of BT_NOTIFICATION_ITERATOR_STATUS_END).

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
include/babeltrace/graph/connection-internal.h
include/babeltrace/graph/notification-iterator-internal.h
include/babeltrace/graph/notification-iterator.h
lib/graph/component.c
lib/graph/connection.c
lib/graph/graph.c
lib/graph/iterator.c
This page took 0.025631 seconds and 4 git commands to generate.