Bug#905033: xserver-xorg-input-elographics: locks up system on EOF from touchscreen
Package: xserver-xorg-input-elographics
Version: 1:1.4.1-1
Severity: normal
Tags: patch
When reading from the touchscreen device returns 0 (EOF), the driver
goes into an endless loop of poll and read. This locks up the Xorg
server, and when trying to kill it with -9, it hangs the whole
system (no idea how it manages to do that, but only an unfriendly
reboot seems to help):
watchdog: BUG: soft lockup - CPU#7 stuck for 22s! [Xorg:3781]
Patch to handle EOF like error return:
--- src/xf86Elo.c
+++ src/xf86Elo.c
@@ -251,6 +251,10 @@
ErrorF("System error while reading from Elographics touchscreen.");
return !Success;
}
+ if (num_bytes == 0) {
+ ErrorF("EOF while reading from Elographics touchscreen.");
+ return !Success;
+ }
DBG(4, ErrorF("Read %d bytes\n", num_bytes));
while (num_bytes) {
Well, I thought that would help, but it didn't. Seems I
misunderstood the comment above: "Okay, give up."
That's not what I understand by giving up, it still keeps retrying
and spamming the log with "EOF while reading from Elographics
touchscreen." -- at this point I also noticed the missing "\n" in
the error messages.
So without changing too much (the fd is passed by value, so I can't
easily change it; also I don't know when this function is called
from where etc.), for a quick and dirty solution I just reassign the
fd to something harmless. /dev/null doesn't work as it always
returns ready in poll and EOF in read too, so I create a pipe,
discard one end, so the other end will be not ready for reading.
This seems to work for me, but a permanent solution should probably
do something more elegant:
--- src/xf86Elo.c
+++ src/xf86Elo.c
@@ -58,6 +58,8 @@
#include "xf86Module.h"
+#include <unistd.h>
+
/**
* models to be treated specially.
*/
@@ -248,7 +250,18 @@
* Okay, give up.
*/
if (num_bytes < 0) {
- ErrorF("System error while reading from Elographics touchscreen.");
+ ErrorF("System error while reading from Elographics touchscreen.\n");
+ return !Success;
+ }
+ if (num_bytes == 0) {
+ /*
+ * Avoid reading from fd again, quick and dirty. Discard one end of a pipe,
+ * so the other end never gets EOF (unlike /dev/null) or reads anything.
+ */
+ int dummy[2];
+ pipe(dummy);
+ dup2(dummy[0], fd);
+ ErrorF("EOF while reading from Elographics touchscreen.\n");
return !Success;
}
DBG(4, ErrorF("Read %d bytes\n", num_bytes));
Reply to: