fix race condition when dropping Ports
Jack2 calls back from a notification thread and the callback (PortManager::connect_callback()) could end up holding the final reference on 1 or more ports. The ports would then be unregistered as we leave the callback scope, which is illegal (no server calls from a notification thread)
This commit is contained in:
parent
fdf63ace6a
commit
448902f870
@ -405,6 +405,7 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
boost::shared_ptr<Port> port;
|
boost::shared_ptr<Port> port;
|
||||||
|
vector<boost::shared_ptr<Port> > deleted_ports;
|
||||||
|
|
||||||
changed = false;
|
changed = false;
|
||||||
|
|
||||||
@ -418,11 +419,30 @@ IO::ensure_ports_locked (ChanCount count, bool clear, bool& changed)
|
|||||||
|
|
||||||
assert(port);
|
assert(port);
|
||||||
_ports.remove(port);
|
_ports.remove(port);
|
||||||
|
|
||||||
|
/* hold a reference to the port so that we can ensure
|
||||||
|
* that this thread, and not a JACK notification thread,
|
||||||
|
* holds the final reference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
deleted_ports.push_back (port);
|
||||||
_session.engine().unregister_port (port);
|
_session.engine().unregister_port (port);
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this will drop the final reference to the deleted ports,
|
||||||
|
* which will in turn call their destructors, which will in
|
||||||
|
* turn call the backend to unregister them.
|
||||||
|
*
|
||||||
|
* There will no connect/disconnect or register/unregister
|
||||||
|
* callbacks from the backend until we get here, because
|
||||||
|
* they are driven by the Port destructor. The destructor
|
||||||
|
* will not execute until we drop the final reference,
|
||||||
|
* which all happens right .... here.
|
||||||
|
*/
|
||||||
|
deleted_ports.clear ();
|
||||||
|
|
||||||
/* create any necessary new ports */
|
/* create any necessary new ports */
|
||||||
while (n_ports().get(*t) < n) {
|
while (n_ports().get(*t) < n) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user