mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
impl-node: improve the node unprepare function
do_node_unprepare runs in both the server and the client when a node is stopped. On the server size, set the status to FINISHED and trigger any targets. This ensures the node will not be scheduled in this cycle anymore. We have to do this because we can't know if the node is still alive or not. When the client receives the stop message, it will unprepare and set the status to INACTIVE. This ensures the driver will no longer trigger the node. If the server didn't already trigger the targets, do this in the remote node then. This avoid a race where both the client and the server are setting the status and if the INACTIVE state is set by the server, it might stall processing of the client. Fixes #4840
This commit is contained in:
parent
d6488c5351
commit
2891e579a1
1 changed files with 10 additions and 6 deletions
|
|
@ -240,17 +240,21 @@ do_node_unprepare(struct spa_loop *loop, bool async, uint32_t seq,
|
|||
{
|
||||
struct pw_impl_node *this = user_data;
|
||||
struct pw_node_target *t;
|
||||
int old_state;
|
||||
int old_state, new_state;
|
||||
uint64_t trigger = 0;
|
||||
|
||||
pw_log_trace("%p: unprepare %d remote:%d exported:%d", this, this->rt.prepared,
|
||||
this->remote, this->exported);
|
||||
|
||||
/* We mark ourself as finished now, this will avoid going further into the process loop
|
||||
* in case our fd was ready (removing ourselfs from the loop should avoid that as well).
|
||||
* If we were supposed to be scheduled make sure we continue the graph for the peers we
|
||||
* were supposed to trigger */
|
||||
old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, PW_NODE_ACTIVATION_INACTIVE);
|
||||
/* The remote client will INACTIVE itself and remove itself from the loop to avoid
|
||||
* being scheduled.
|
||||
* The server will mark remote nodes as FINISHED. This will make sure the node will not
|
||||
* trigger the peers anymore when it will stop because we do that on the server side
|
||||
* because the client might simply be dead and not able to resume anything.
|
||||
*/
|
||||
new_state = this->remote ? PW_NODE_ACTIVATION_FINISHED : PW_NODE_ACTIVATION_INACTIVE;
|
||||
|
||||
old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, new_state);
|
||||
if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state))
|
||||
trigger = get_time_ns(this->rt.target.system);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue