Package: inputattach
Version: 1:1.4-1
Severity: important
Tags: upstream patch

When booting, inputattach tries to hook up my serial port for some w8001 action 
but causes the CPU instead to spin at 100%.  strace'ing shows it's spinning on 
read(3,NULL,0) and is returning EBUSY; /proc/$PID/fd/3 points to /dev/ttyS0.

Looking at the source I found the following caused the problem:

http://linuxconsole.svn.sourceforge.net/viewvc/linuxconsole?view=revision&revision=2422

http://linuxconsole.svn.sourceforge.net/viewvc/linuxconsole/trunk/utils/inputattach.c?r1=2412&r2=2422&pathrev=2422

We need to tell Kees Cook that errno does actually have more than two values 
(not just zero and EINTR) and reading manpages helps ;P

Attached is a fix that seems to work after a suspend/resume cycle and of course 
on a fresh boot.

Thanks though to Kee's on finding what the actual hiccup was in the first place 
though, it's removed another thing off my todo list.

Cheers

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (900, 'unstable'), (500, 'experimental'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.39-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages inputattach depends on:
ii  libc6                         2.13-7     Embedded GNU C Library: Shared lib

inputattach recommends no packages.

inputattach suggests no packages.

-- no debconf information
--- joystick-1.4.orig/utils/inputattach.c	2011-05-16 22:05:56.000000000 +0100
+++ joystick-1.4/utils/inputattach.c	2011-06-25 10:49:00.000000000 +0100
@@ -607,6 +607,9 @@
 	puts("");
 }
 
+/* palmed wisdom from http://stackoverflow.com/questions/1674162/ */
+#define RETRY_ERROR(x) (x == EAGAIN || x == EWOULDBLOCK || x == EINTR)
+
 int main(int argc, char **argv)
 {
 	unsigned long devt;
@@ -738,7 +741,13 @@
 		retval = EXIT_FAILURE;
 	}
 
-	for (errno = 0; errno != EINTR; read(fd, NULL, 0)) ;
+	do {
+		i = read(fd, NULL, 0);
+		if (i == -1) {
+			if (RETRY_ERROR(errno))
+				continue;
+		}
+	} while (!i);
 
 	ldisc = 0;
 	ioctl(fd, TIOCSETD, &ldisc);

Reply via email to