[master 2/4] Ignore EINTR from os.close instead of retrying the call

dashea installerbot-noreply at redhat.com
Tue Jun 23 14:54:01 UTC 2015


From: David Shea <dshea at redhat.com>

Retrying close in Linux is considered a bad idea, it turns out.
---
 blivet/devicelibs/edd.py  |  2 +-
 blivet/devices/file.py    |  2 +-
 blivet/devices/optical.py |  2 +-
 blivet/fcoe.py            |  2 +-
 blivet/iscsi.py           |  4 ++--
 blivet/util.py            | 18 ++++++++++++++++--
 6 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/blivet/devicelibs/edd.py b/blivet/devicelibs/edd.py
index 08a713f..7c99bb1 100644
--- a/blivet/devicelibs/edd.py
+++ b/blivet/devicelibs/edd.py
@@ -165,7 +165,7 @@ def collect_mbrs(devices):
             # The signature is the unsigned integer at byte 440:
             os.lseek(fd, 440, 0)
             mbrsig = struct.unpack('I', util.eintr_retry_call(os.read, fd, 4))
-            util.eintr_retry_call(os.close, fd)
+            util.eintr_ignore(os.close, fd)
         except OSError as e:
             log.warning("edd: error reading mbrsig from disk %s: %s",
                         dev.name, str(e))
diff --git a/blivet/devices/file.py b/blivet/devices/file.py
index f104568..a2845eb 100644
--- a/blivet/devices/file.py
+++ b/blivet/devices/file.py
@@ -119,7 +119,7 @@ def _create(self):
             size_target = zero * rem
             util.eintr_retry_call(os.write, fd, size_target.encode("utf-8"))
 
-        util.eintr_retry_call(os.close, fd)
+        util.eintr_ignore(os.close, fd)
 
     def _destroy(self):
         """ Destroy the device. """
diff --git a/blivet/devices/optical.py b/blivet/devices/optical.py
index 3f8fcd2..591fd01 100644
--- a/blivet/devices/optical.py
+++ b/blivet/devices/optical.py
@@ -63,7 +63,7 @@ def mediaPresent(self):
             else:
                 return True
         else:
-            util.eintr_retry_call(os.close, fd)
+            util.eintr_ignore(os.close, fd)
             return True
 
     def eject(self):
diff --git a/blivet/fcoe.py b/blivet/fcoe.py
index 1723207..a7d7a4c 100644
--- a/blivet/fcoe.py
+++ b/blivet/fcoe.py
@@ -165,7 +165,7 @@ def write(self, root):
             else:
                 config += 'AUTO_VLAN="no"\n'
             util.eintr_retry_call(os.write, fd, config.encode('utf-8'))
-            util.eintr_retry_call(os.close, fd)
+            util.eintr_ignore(os.close, fd)
 
         return
 
diff --git a/blivet/iscsi.py b/blivet/iscsi.py
index 160a243..5aa3d4b 100644
--- a/blivet/iscsi.py
+++ b/blivet/iscsi.py
@@ -272,7 +272,7 @@ def startup(self):
         fd = util.eintr_retry_call(os.open, INITIATOR_FILE, os.O_RDWR | os.O_CREAT)
         initiator_name = "InitiatorName=%s\n" % self.initiator
         util.eintr_retry_call(os.write, fd, initiator_name.encode("utf-8"))
-        util.eintr_retry_call(os.close, fd)
+        util.eintr_ignore(os.close, fd)
         self.initiatorSet = True
 
         for fulldir in (os.path.join("/var/lib/iscsi", d) for d in \
@@ -493,7 +493,7 @@ def write(self, root, storage):
         fd = util.eintr_retry_call(os.open, root + INITIATOR_FILE, os.O_RDWR | os.O_CREAT)
         initiator_name = "InitiatorName=%s\n" % self.initiator
         util.eintr_retry_call(os.write, fd, initiator_name.encode("utf-8"))
-        util.eintr_retry_call(os.close, fd)
+        util.eintr_ignore(os.close, fd)
 
         # copy "db" files.  *sigh*
         if os.path.isdir(root + "/var/lib/iscsi"):
diff --git a/blivet/util.py b/blivet/util.py
index b39308b..30db569 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -528,7 +528,7 @@ def create_sparse_tempfile(name, size):
         :returns: the path to the newly created file
     """
     (fd, path) = tempfile.mkstemp(prefix="blivet.", suffix="-%s" % name)
-    eintr_retry_call(os.close, fd)
+    eintr_ignore(os.close, fd)
     create_sparse_file(path, size)
     return path
 
@@ -541,7 +541,7 @@ def create_sparse_file(path, size):
     """
     fd = eintr_retry_call(os.open, path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC)
     eintr_retry_call(os.ftruncate, fd, size)
-    eintr_retry_call(os.close, fd)
+    eintr_ignore(os.close, fd)
 
 @contextmanager
 def sparsetmpfile(name, size):
@@ -637,3 +637,17 @@ def eintr_retry_call(func, *args, **kwargs):
             if e.errno == errno.EINTR:
                 continue
             raise
+
+def eintr_ignore(func, *args, **kwargs):
+    """Call a function and ignore EINTR.
+
+       This is useful for calls to close() and dup2(), which can return EINTR
+       but which should *not* be retried, since by the time the return the
+       file descriptor is already closed.
+    """
+    try:
+        return func(*args, **kwargs)
+    except (OSError, IOError) as e:
+        if e.errno == errno.EINTR:
+            pass
+        raise


-- 
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/75cccc1d1453fdabc88fe5776d9dd4df4984b5f4


More information about the anaconda-patches mailing list