Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: seq-dummy: remove deadlock-causing events on close

When the last subscriber to a "Through" port has been removed, the
subscribed destination ports might still be active, so it would be
wrong to send "all sounds off" and "reset controller" events to them.
The proper place for such a shutdown would be the closing of the actual
MIDI port (and close_substream() in rawmidi.c already can do this).

This also fixes a deadlock when dummy_unuse() tries to send events to
its own port that is already locked because it is being freed.

Reported-by: Peter Billam <peter@www.pjb.com.au>
Cc: <stable@vger.kernel.org>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Clemens Ladisch and committed by
Takashi Iwai
0767e95b 6715f728

-31
-31
sound/core/seq/seq_dummy.c
··· 82 82 static int my_client = -1; 83 83 84 84 /* 85 - * unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events 86 - * to subscribers. 87 - * Note: this callback is called only after all subscribers are removed. 88 - */ 89 - static int 90 - dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info) 91 - { 92 - struct snd_seq_dummy_port *p; 93 - int i; 94 - struct snd_seq_event ev; 95 - 96 - p = private_data; 97 - memset(&ev, 0, sizeof(ev)); 98 - if (p->duplex) 99 - ev.source.port = p->connect; 100 - else 101 - ev.source.port = p->port; 102 - ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS; 103 - ev.type = SNDRV_SEQ_EVENT_CONTROLLER; 104 - for (i = 0; i < 16; i++) { 105 - ev.data.control.channel = i; 106 - ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF; 107 - snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); 108 - ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS; 109 - snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0); 110 - } 111 - return 0; 112 - } 113 - 114 - /* 115 85 * event input callback - just redirect events to subscribers 116 86 */ 117 87 static int ··· 145 175 | SNDRV_SEQ_PORT_TYPE_PORT; 146 176 memset(&pcb, 0, sizeof(pcb)); 147 177 pcb.owner = THIS_MODULE; 148 - pcb.unuse = dummy_unuse; 149 178 pcb.event_input = dummy_input; 150 179 pcb.private_free = dummy_free; 151 180 pcb.private_data = rec;