Skip to content

Commit 0914f79

Browse files
committed
ALSA: Avoid endless sleep after disconnect
When disconnect callback is called, each component should wake up sleepers and check card->shutdown flag for avoiding the endless sleep blocking the proper resource release. Cc: <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent a0830db commit 0914f79

File tree

6 files changed

+46
-1
lines changed

6 files changed

+46
-1
lines changed

sound/core/control.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
14371437
spin_unlock_irq(&ctl->read_lock);
14381438
schedule();
14391439
remove_wait_queue(&ctl->change_sleep, &wait);
1440+
if (ctl->card->shutdown)
1441+
return -ENODEV;
14401442
if (signal_pending(current))
14411443
return -ERESTARTSYS;
14421444
spin_lock_irq(&ctl->read_lock);

sound/core/hwdep.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
131131
mutex_unlock(&hw->open_mutex);
132132
schedule();
133133
mutex_lock(&hw->open_mutex);
134+
if (hw->card->shutdown) {
135+
err = -ENODEV;
136+
break;
137+
}
134138
if (signal_pending(current)) {
135139
err = -ERESTARTSYS;
136140
break;
@@ -462,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
462466
mutex_unlock(&register_mutex);
463467
return -EINVAL;
464468
}
469+
mutex_lock(&hwdep->open_mutex);
470+
wake_up(&hwdep->open_wait);
465471
#ifdef CONFIG_SND_OSSEMUL
466472
if (hwdep->ossreg)
467473
snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
468474
#endif
469475
snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
470476
list_del_init(&hwdep->list);
477+
mutex_unlock(&hwdep->open_mutex);
471478
mutex_unlock(&register_mutex);
472479
return 0;
473480
}

sound/core/oss/pcm_oss.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
24412441
mutex_unlock(&pcm->open_mutex);
24422442
schedule();
24432443
mutex_lock(&pcm->open_mutex);
2444+
if (pcm->card->shutdown) {
2445+
err = -ENODEV;
2446+
break;
2447+
}
24442448
if (signal_pending(current)) {
24452449
err = -ERESTARTSYS;
24462450
break;

sound/core/pcm.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,12 +1087,16 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
10871087
goto unlock;
10881088

10891089
mutex_lock(&pcm->open_mutex);
1090+
wake_up(&pcm->open_wait);
10901091
list_del_init(&pcm->list);
10911092
for (cidx = 0; cidx < 2; cidx++)
10921093
for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
10931094
snd_pcm_stream_lock_irq(substream);
1094-
if (substream->runtime)
1095+
if (substream->runtime) {
10951096
substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
1097+
wake_up(&substream->runtime->sleep);
1098+
wake_up(&substream->runtime->tsleep);
1099+
}
10961100
snd_pcm_stream_unlock_irq(substream);
10971101
}
10981102
list_for_each_entry(notify, &snd_pcm_notify_list, list) {

sound/core/pcm_native.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
15181518
down_read(&snd_pcm_link_rwsem);
15191519
snd_pcm_stream_lock_irq(substream);
15201520
remove_wait_queue(&to_check->sleep, &wait);
1521+
if (card->shutdown) {
1522+
result = -ENODEV;
1523+
break;
1524+
}
15211525
if (tout == 0) {
15221526
if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
15231527
result = -ESTRPIPE;
@@ -2169,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
21692173
mutex_unlock(&pcm->open_mutex);
21702174
schedule();
21712175
mutex_lock(&pcm->open_mutex);
2176+
if (pcm->card->shutdown) {
2177+
err = -ENODEV;
2178+
break;
2179+
}
21722180
if (signal_pending(current)) {
21732181
err = -ERESTARTSYS;
21742182
break;

sound/core/rawmidi.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
424424
mutex_unlock(&rmidi->open_mutex);
425425
schedule();
426426
mutex_lock(&rmidi->open_mutex);
427+
if (rmidi->card->shutdown) {
428+
err = -ENODEV;
429+
break;
430+
}
427431
if (signal_pending(current)) {
428432
err = -ERESTARTSYS;
429433
break;
@@ -995,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
995999
spin_unlock_irq(&runtime->lock);
9961000
schedule();
9971001
remove_wait_queue(&runtime->sleep, &wait);
1002+
if (rfile->rmidi->card->shutdown)
1003+
return -ENODEV;
9981004
if (signal_pending(current))
9991005
return result > 0 ? result : -ERESTARTSYS;
10001006
if (!runtime->avail)
@@ -1238,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
12381244
spin_unlock_irq(&runtime->lock);
12391245
timeout = schedule_timeout(30 * HZ);
12401246
remove_wait_queue(&runtime->sleep, &wait);
1247+
if (rfile->rmidi->card->shutdown)
1248+
return -ENODEV;
12411249
if (signal_pending(current))
12421250
return result > 0 ? result : -ERESTARTSYS;
12431251
if (!runtime->avail && !timeout)
@@ -1613,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
16131621
static int snd_rawmidi_dev_disconnect(struct snd_device *device)
16141622
{
16151623
struct snd_rawmidi *rmidi = device->device_data;
1624+
int dir;
16161625

16171626
mutex_lock(&register_mutex);
1627+
mutex_lock(&rmidi->open_mutex);
1628+
wake_up(&rmidi->open_wait);
16181629
list_del_init(&rmidi->list);
1630+
for (dir = 0; dir < 2; dir++) {
1631+
struct snd_rawmidi_substream *s;
1632+
list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
1633+
if (s->runtime)
1634+
wake_up(&s->runtime->sleep);
1635+
}
1636+
}
1637+
16191638
#ifdef CONFIG_SND_OSSEMUL
16201639
if (rmidi->ossreg) {
16211640
if ((int)rmidi->device == midi_map[rmidi->card->number]) {
@@ -1630,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
16301649
}
16311650
#endif /* CONFIG_SND_OSSEMUL */
16321651
snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
1652+
mutex_unlock(&rmidi->open_mutex);
16331653
mutex_unlock(&register_mutex);
16341654
return 0;
16351655
}

0 commit comments

Comments
 (0)