[alsa-devel] [PATCH v2 1/1] ALSA: seq: Continue broadcasting events to ports if one of them fails

Takashi Iwai tiwai at suse.de
Wed Jun 4 17:31:47 CEST 2014


At Wed,  4 Jun 2014 11:20:55 -0400,
Adam Goode wrote:
> 
> Sometimes PORT_EXIT messages are lost when a process is exiting.
> This happens if you subscribe to the announce port with client A,
> then subscribe to the announce port with client B, then kill client A.
> Client B will not see the PORT_EXIT message because client A's port is
> closing and is earlier in the announce port subscription list. The
> for each loop will try to send the announcement to client A and fail,
> then will stop trying to broadcast to other ports. Killing B works fine
> since the announcement will already have gone to A. The CLIENT_EXIT
> message does not get lost.
> 
> How to reproduce problem:
> 
> *** termA
> $ aseqdump -p 0:1
>   0:1   Port subscribed            0:1 -> 128:0
> 
> *** termB
> $ aseqdump -p 0:1
> 
> *** termA
>   0:1   Client start               client 129
>   0:1   Port start                 129:0
>   0:1   Port subscribed            0:1 -> 129:0
> 
> *** termB
>   0:1   Port subscribed            0:1 -> 129:0
> 
> *** termA
> ^C
> 
> *** termB
>   0:1   Client exit                client 128
>    <--- expected Port exit as well (before client exit)
> 
> Signed-off-by: Adam Goode <agoode at google.com>

Applied, thanks.


Takashi


> 
> diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
> index 9ca5e64..225c7315 100644
> --- a/sound/core/seq/seq_clientmgr.c
> +++ b/sound/core/seq/seq_clientmgr.c
> @@ -660,7 +660,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
>  				  int atomic, int hop)
>  {
>  	struct snd_seq_subscribers *subs;
> -	int err = 0, num_ev = 0;
> +	int err, result = 0, num_ev = 0;
>  	struct snd_seq_event event_saved;
>  	struct snd_seq_client_port *src_port;
>  	struct snd_seq_port_subs_info *grp;
> @@ -685,8 +685,12 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
>  						  subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);
>  		err = snd_seq_deliver_single_event(client, event,
>  						   0, atomic, hop);
> -		if (err < 0)
> -			break;
> +		if (err < 0) {
> +			/* save first error that occurs and continue */
> +			if (!result)
> +				result = err;
> +			continue;
> +		}
>  		num_ev++;
>  		/* restore original event record */
>  		*event = event_saved;
> @@ -697,7 +701,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
>  		up_read(&grp->list_mutex);
>  	*event = event_saved; /* restore */
>  	snd_seq_port_unlock(src_port);
> -	return (err < 0) ? err : num_ev;
> +	return (result < 0) ? result : num_ev;
>  }
>  
>  
> @@ -709,7 +713,7 @@ static int port_broadcast_event(struct snd_seq_client *client,
>  				struct snd_seq_event *event,
>  				int atomic, int hop)
>  {
> -	int num_ev = 0, err = 0;
> +	int num_ev = 0, err, result = 0;
>  	struct snd_seq_client *dest_client;
>  	struct snd_seq_client_port *port;
>  
> @@ -724,14 +728,18 @@ static int port_broadcast_event(struct snd_seq_client *client,
>  		err = snd_seq_deliver_single_event(NULL, event,
>  						   SNDRV_SEQ_FILTER_BROADCAST,
>  						   atomic, hop);
> -		if (err < 0)
> -			break;
> +		if (err < 0) {
> +			/* save first error that occurs and continue */
> +			if (!result)
> +				result = err;
> +			continue;
> +		}
>  		num_ev++;
>  	}
>  	read_unlock(&dest_client->ports_lock);
>  	snd_seq_client_unlock(dest_client);
>  	event->dest.port = SNDRV_SEQ_ADDRESS_BROADCAST; /* restore */
> -	return (err < 0) ? err : num_ev;
> +	return (result < 0) ? result : num_ev;
>  }
>  
>  /*
> @@ -741,7 +749,7 @@ static int port_broadcast_event(struct snd_seq_client *client,
>  static int broadcast_event(struct snd_seq_client *client,
>  			   struct snd_seq_event *event, int atomic, int hop)
>  {
> -	int err = 0, num_ev = 0;
> +	int err, result = 0, num_ev = 0;
>  	int dest;
>  	struct snd_seq_addr addr;
>  
> @@ -760,12 +768,16 @@ static int broadcast_event(struct snd_seq_client *client,
>  			err = snd_seq_deliver_single_event(NULL, event,
>  							   SNDRV_SEQ_FILTER_BROADCAST,
>  							   atomic, hop);
> -		if (err < 0)
> -			break;
> +		if (err < 0) {
> +			/* save first error that occurs and continue */
> +			if (!result)
> +				result = err;
> +			continue;
> +		}
>  		num_ev += err;
>  	}
>  	event->dest = addr; /* restore */
> -	return (err < 0) ? err : num_ev;
> +	return (result < 0) ? result : num_ev;
>  }
>  
>  
> -- 
> 2.0.0.526.g5318336
> 


More information about the Alsa-devel mailing list