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 <[email protected]>
---
  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
_______________________________________________
pulseaudio-discuss mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss

Reply via email to