Fix hanging firmware updater when device is unresponsive.

Previously the updater unconditionally read from the device. In
case of an unresponsive device this lead to a hanging process.
Since the updater is triggered by udevd the event queue of udevd
gets blocked which leads to followup problems - see the attached bug.

Now we check for the availibility of data (using select) prior to
starting to read. In case select runs into the one second timeout
we print an error message and exit the updater.

BUG=b:117422687
TEST=Deployed to local fizz box with one of the problematic devices
attached. sis_fw_updater exits after a second and the syslog shows
the error message.

Change-Id: If7ce402c10edd172265c02a7684195f7e7d38d23
Reviewed-on: https://chromium-review.googlesource.com/1297490
Commit-Ready: Daniel Fenner <dfenner@google.com>
Tested-by: Daniel Fenner <dfenner@google.com>
Reviewed-by: Stefan Adolfsson <sadolfsson@chromium.org>
diff --git a/src/sis_fw_updater.cc b/src/sis_fw_updater.cc
index bb4f695..c5a40c0 100644
--- a/src/sis_fw_updater.cc
+++ b/src/sis_fw_updater.cc
@@ -4655,6 +4655,21 @@
 #ifdef VIA_IOCTL
 
   do {
+    fd_set fd_read;
+    FD_ZERO(&fd_read);
+    FD_SET(m_fd, &fd_read);
+
+    struct timeval one_second_timeout;
+    one_second_timeout.tv_sec = 1;
+    one_second_timeout.tv_usec = 0;
+
+    if (select(m_fd + 1, &fd_read, NULL, NULL, &one_second_timeout) != 1) {
+      // The methods calling this do not propagate the return value properly and
+      // I see no way of recovering from this error.
+      close(m_fd);
+      LOG(ERROR) << "SiSTouch did not respond. Terminating firmware update.";
+      exit(1);
+    }
     ret = read(m_fd, buf, size);
     if (ret > 0 && (buf[0] != report_id))
       continue;