提交 0767e95b 编写于 作者: C Clemens Ladisch 提交者: Takashi Iwai

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: NPeter Billam <peter@www.pjb.com.au>
Cc: <stable@vger.kernel.org>
Signed-off-by: NClemens Ladisch <clemens@ladisch.de>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 6715f728
...@@ -81,36 +81,6 @@ struct snd_seq_dummy_port { ...@@ -81,36 +81,6 @@ struct snd_seq_dummy_port {
static int my_client = -1; static int my_client = -1;
/*
* unuse callback - send ALL_SOUNDS_OFF and RESET_CONTROLLERS events
* to subscribers.
* Note: this callback is called only after all subscribers are removed.
*/
static int
dummy_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
struct snd_seq_dummy_port *p;
int i;
struct snd_seq_event ev;
p = private_data;
memset(&ev, 0, sizeof(ev));
if (p->duplex)
ev.source.port = p->connect;
else
ev.source.port = p->port;
ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
for (i = 0; i < 16; i++) {
ev.data.control.channel = i;
ev.data.control.param = MIDI_CTL_ALL_SOUNDS_OFF;
snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
ev.data.control.param = MIDI_CTL_RESET_CONTROLLERS;
snd_seq_kernel_client_dispatch(p->client, &ev, 0, 0);
}
return 0;
}
/* /*
* event input callback - just redirect events to subscribers * event input callback - just redirect events to subscribers
*/ */
...@@ -175,7 +145,6 @@ create_port(int idx, int type) ...@@ -175,7 +145,6 @@ create_port(int idx, int type)
| SNDRV_SEQ_PORT_TYPE_PORT; | SNDRV_SEQ_PORT_TYPE_PORT;
memset(&pcb, 0, sizeof(pcb)); memset(&pcb, 0, sizeof(pcb));
pcb.owner = THIS_MODULE; pcb.owner = THIS_MODULE;
pcb.unuse = dummy_unuse;
pcb.event_input = dummy_input; pcb.event_input = dummy_input;
pcb.private_free = dummy_free; pcb.private_free = dummy_free;
pcb.private_data = rec; pcb.private_data = rec;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册