A file descriptor closer that uses HANDLE_EINTR.

- A new flavor of ScopedFdCloser which wraps close() with HANDLE_EINTR,
  which will retry closing the file descriptor if the last close attempt
  was interrupted by EINTR. This appears to be a recommended practice
  per POSIX documentation.

- Both ScopedFdCloser and ScopedEintrSafeFdCloser ensure a successful
  close() prior to resetting the file descriptor.

- Better use of HANDLE_EINTR elsewhere: just realized that this macro
  returns the value of the last evaluation of its argument.

BUG=chromium-os:25397
TEST=Image builds properly; GPIO functionality works (x86-alex).

Change-Id: I3425bb580499c7138cd31917011662d33ffab8a6
Reviewed-on: https://gerrit.chromium.org/gerrit/17079
Reviewed-by: Andrew de los Reyes <adlr@chromium.org>
Reviewed-by: Darin Petkov <petkov@chromium.org>
Commit-Ready: Gilad Arnold <garnold@chromium.org>
Tested-by: Gilad Arnold <garnold@chromium.org>
diff --git a/utils.h b/utils.h
index b0b28a8..728d992 100644
--- a/utils.h
+++ b/utils.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include <base/eintr_wrapper.h>
 #include <ext2fs/ext2fs.h>
 #include <glib.h>
 
@@ -276,8 +277,8 @@
   explicit ScopedFdCloser(int* fd) : fd_(fd), should_close_(true) {}
   ~ScopedFdCloser() {
     if (should_close_ && fd_ && (*fd_ >= 0)) {
-      close(*fd_);
-      *fd_ = -1;
+      if (!close(*fd_))
+        *fd_ = -1;
     }
   }
   void set_should_close(bool should_close) { should_close_ = should_close; }
@@ -287,6 +288,23 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedFdCloser);
 };
 
+// An EINTR-immune file descriptor closer.
+class ScopedEintrSafeFdCloser {
+ public:
+  explicit ScopedEintrSafeFdCloser(int* fd) : fd_(fd), should_close_(true) {}
+  ~ScopedEintrSafeFdCloser() {
+    if (should_close_ && fd_ && (*fd_ >= 0)) {
+      if (!HANDLE_EINTR(close(*fd_)))
+        *fd_ = -1;
+    }
+  }
+  void set_should_close(bool should_close) { should_close_ = should_close; }
+ private:
+  int* fd_;
+  bool should_close_;
+  DISALLOW_COPY_AND_ASSIGN(ScopedEintrSafeFdCloser);
+};
+
 // Utility class to close a file system
 class ScopedExt2fsCloser {
  public: