From 45850439b3b28ff7ed0d1455f62f5a85572caefa Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 27 Feb 2006 09:54:57 +0000 Subject: [PATCH] Do not abort in snd_xxx_close() functions Remove several memory leaks by not aborting prematurely from a snd_xxx_close() function when some operation fails. This can happen when a USB device was unplugged. --- src/hwdep/hwdep.c | 5 ++--- src/pcm/pcm.c | 11 +++++++---- src/pcm/pcm_hooks.c | 9 ++++++--- src/pcm/pcm_hw.c | 5 ++--- src/pcm/pcm_plug.c | 5 +---- src/rawmidi/rawmidi.c | 5 ++--- src/rawmidi/rawmidi_hw.c | 6 ++++-- src/seq/seq.c | 4 +--- src/seq/seq_hw.c | 6 ++++-- src/timer/timer.c | 5 ++--- src/timer/timer_query.c | 5 ++--- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/hwdep/hwdep.c b/src/hwdep/hwdep.c index f0c8f9d0..6a5e7872 100644 --- a/src/hwdep/hwdep.c +++ b/src/hwdep/hwdep.c @@ -206,12 +206,11 @@ int snd_hwdep_close(snd_hwdep_t *hwdep) { int err; assert(hwdep); - if ((err = hwdep->ops->close(hwdep)) < 0) - return err; + err = hwdep->ops->close(hwdep); if (hwdep->name) free(hwdep->name); free(hwdep); - return 0; + return err; } /** diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 43d87c35..0af6f2aa 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -668,13 +668,13 @@ snd_pcm_stream_t snd_pcm_stream(snd_pcm_t *pcm) */ int snd_pcm_close(snd_pcm_t *pcm) { - int err; + int res = 0, err; assert(pcm); if (pcm->setup && !pcm->donot_close) { snd_pcm_drop(pcm); err = snd_pcm_hw_free(pcm); if (err < 0) - return err; + res = err; } if (pcm->mmap_channels) snd_pcm_munmap(pcm); @@ -684,8 +684,11 @@ int snd_pcm_close(snd_pcm_t *pcm) } err = pcm->ops->close(pcm->op_arg); if (err < 0) - return err; - return snd_pcm_free(pcm); + res = err; + err = snd_pcm_free(pcm); + if (err < 0) + res = err; + return res; } /** diff --git a/src/pcm/pcm_hooks.c b/src/pcm/pcm_hooks.c index f5136862..86799877 100644 --- a/src/pcm/pcm_hooks.c +++ b/src/pcm/pcm_hooks.c @@ -55,13 +55,13 @@ static int snd_pcm_hooks_close(snd_pcm_t *pcm) snd_pcm_hooks_t *h = pcm->private_data; struct list_head *pos, *next; unsigned int k; - int err; + int res = 0, err; list_for_each_safe(pos, next, &h->hooks[SND_PCM_HOOK_TYPE_CLOSE]) { snd_pcm_hook_t *hook = list_entry(pos, snd_pcm_hook_t, list); err = hook->func(hook); if (err < 0) - return err; + res = err; } for (k = 0; k <= SND_PCM_HOOK_TYPE_LAST; ++k) { struct list_head *hooks = &h->hooks[k]; @@ -72,7 +72,10 @@ static int snd_pcm_hooks_close(snd_pcm_t *pcm) snd_pcm_hook_remove(hook); } } - return snd_pcm_generic_close(pcm); + err = snd_pcm_generic_close(pcm); + if (err < 0) + res = err; + return res; } static int snd_pcm_hooks_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index 88dab15a..356576fa 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -889,16 +889,15 @@ static int snd_pcm_hw_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED) static int snd_pcm_hw_close(snd_pcm_t *pcm) { snd_pcm_hw_t *hw = pcm->private_data; - int err; + int err = 0; if (close(hw->fd)) { err = -errno; SYSMSG("close failed\n"); - return err; } snd_pcm_hw_munmap_status(pcm); snd_pcm_hw_munmap_control(pcm); free(hw); - return 0; + return err; } static snd_pcm_sframes_t snd_pcm_hw_mmap_commit(snd_pcm_t *pcm, diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 2bcc62dc..15204d75 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -64,10 +64,7 @@ static int snd_pcm_plug_close(snd_pcm_t *pcm) int err, result = 0; if (plug->ttable) free(plug->ttable); - if (plug->gen.slave != plug->req_slave) { - SNDERR("plug slaves mismatch"); - return -EINVAL; - } + assert(plug->gen.slave == plug->req_slave); if (plug->gen.close_slave) { snd_pcm_unlink_hw_ptr(pcm, plug->req_slave); snd_pcm_unlink_appl_ptr(pcm, plug->req_slave); diff --git a/src/rawmidi/rawmidi.c b/src/rawmidi/rawmidi.c index fe19886e..2d509097 100644 --- a/src/rawmidi/rawmidi.c +++ b/src/rawmidi/rawmidi.c @@ -341,14 +341,13 @@ int snd_rawmidi_close(snd_rawmidi_t *rawmidi) { int err; assert(rawmidi); - if ((err = rawmidi->ops->close(rawmidi)) < 0) - return err; + err = rawmidi->ops->close(rawmidi); if (rawmidi->name) free(rawmidi->name); if (rawmidi->dl_handle) snd_dlclose(rawmidi->dl_handle); free(rawmidi); - return 0; + return err; } /** diff --git a/src/rawmidi/rawmidi_hw.c b/src/rawmidi/rawmidi_hw.c index 6d2316f7..b15dadb6 100644 --- a/src/rawmidi/rawmidi_hw.c +++ b/src/rawmidi/rawmidi_hw.c @@ -48,15 +48,17 @@ typedef struct { static int snd_rawmidi_hw_close(snd_rawmidi_t *rmidi) { snd_rawmidi_hw_t *hw = rmidi->private_data; + int err = 0; + hw->open--; if (hw->open) return 0; if (close(hw->fd)) { + err = -errno; SYSERR("close failed\n"); - return -errno; } free(hw); - return 0; + return err; } static int snd_rawmidi_hw_nonblock(snd_rawmidi_t *rmidi, int nonblock) diff --git a/src/seq/seq.c b/src/seq/seq.c index df7b64e6..07954a35 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -1029,8 +1029,6 @@ int snd_seq_close(snd_seq_t *seq) int err; assert(seq); err = seq->ops->close(seq); - if (err < 0) - return err; if (seq->obuf) free(seq->obuf); if (seq->ibuf) @@ -1040,7 +1038,7 @@ int snd_seq_close(snd_seq_t *seq) if (seq->name) free(seq->name); free(seq); - return 0; + return err; } /** diff --git a/src/seq/seq_hw.c b/src/seq/seq_hw.c index a2a01455..c92f3648 100644 --- a/src/seq/seq_hw.c +++ b/src/seq/seq_hw.c @@ -42,12 +42,14 @@ typedef struct { static int snd_seq_hw_close(snd_seq_t *seq) { snd_seq_hw_t *hw = seq->private_data; + int err = 0; + if (close(hw->fd)) { + err = -errno; SYSERR("close failed\n"); - return -errno; } free(hw); - return 0; + return err; } static int snd_seq_hw_nonblock(snd_seq_t *seq, int nonblock) diff --git a/src/timer/timer.c b/src/timer/timer.c index d6ca49bd..8b3da1f2 100644 --- a/src/timer/timer.c +++ b/src/timer/timer.c @@ -242,12 +242,11 @@ int snd_timer_close(snd_timer_t *timer) snd_async_handler_t *h = list_entry(timer->async_handlers.next, snd_async_handler_t, hlist); snd_async_del_handler(h); } - if ((err = timer->ops->close(timer)) < 0) - return err; + err = timer->ops->close(timer); if (timer->name) free(timer->name); free(timer); - return 0; + return err; } /** diff --git a/src/timer/timer_query.c b/src/timer/timer_query.c index 77c9afc2..58c2d5a3 100644 --- a/src/timer/timer_query.c +++ b/src/timer/timer_query.c @@ -196,12 +196,11 @@ int snd_timer_query_close(snd_timer_query_t *timer) { int err; assert(timer); - if ((err = timer->ops->close(timer)) < 0) - return err; + err = timer->ops->close(timer); if (timer->name) free(timer->name); free(timer); - return 0; + return err; } /** -- 2.47.1