[pulseaudio-discuss] [PATCH] module-mmkbd-evdev: Don't crash on failure to close fd
Alexander E. Patrakov
patrakov at gmail.com
Fri Sep 12 01:35:15 PDT 2014
12.09.2014 14:10, David Henningsson wrote:
> If the keyboard is unplugged, it looks like the kernel is reporting
> back -ENODEV when trying to close the fd. This is probably a kernel
> error, but still, it's better to complain than to crash.
>
> Buglink: https://bugs.freedesktop.org/show_bug.cgi?id=80867
> Reported-by: Stelios Bounanos
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> ---
> src/modules/module-mmkbd-evdev.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
The patch neither looks definitely good nor looks definitely bad to me
(but hey, it fixes a crash!). I have verified that there are no other
instances of pa_close in the same module (i.e. that could attempt to
close the same device and thus would need a similar quirk), but am not
sure whether the "log the close() failure" logic belongs here or should
be done generally in pa_close().
I have also looked at the definition of pa_close(). While it is
unrelated to the problem that the patch is trying to solve, I must say
that either any pa_assert_se(pa_close(fd) == 0) in any file is a bug, or
the loop that retries on EINTR inside pa_close() is a bug, or both. The
retry-loop is a bug at least for Linux. Here is why.
https://lwn.net/Articles/576478/
https://lwn.net/Articles/576591/
Even for the hypothetical situation where close() can fail with EINTR,
see the manual page:
> In particular close() should not be retried after an EINTR since this
> may cause a reused descriptor from another thread to be closed.
But it is retried. The worst case is already described above, and the
best case is that it, when retried, fails with EBADFD and causes the
assert to fail.
>
> diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c
> index 9ab7eb9..0b04f0f 100644
> --- a/src/modules/module-mmkbd-evdev.c
> +++ b/src/modules/module-mmkbd-evdev.c
> @@ -256,8 +256,11 @@ void pa__done(pa_module*m) {
> if (u->io)
> m->core->mainloop->io_free(u->io);
>
> - if (u->fd >= 0)
> - pa_assert_se(pa_close(u->fd) == 0);
> + if (u->fd >= 0) {
> + int r = pa_close(u->fd);
> + if (r < 0) /* https://bugs.freedesktop.org/show_bug.cgi?id=80867 */
> + pa_log("Closing fd failed: %s", pa_cstrerror(errno));
> + }
>
> pa_xfree(u->sink_name);
> pa_xfree(u);
--
Alexander E. Patrakov
More information about the pulseaudio-discuss
mailing list