[master 1/1] Do not raise an exception on EINTR from os.close or os.dup2

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


From: David Shea <dshea at redhat.com>

---
 anaconda                      |  2 +-
 pyanaconda/anaconda.py        |  2 +-
 pyanaconda/bootloader.py      | 10 +++++-----
 pyanaconda/exception.py       | 10 +++++-----
 pyanaconda/iutil.py           | 14 +++++++++++++-
 pyanaconda/kickstart.py       |  2 +-
 pyanaconda/vnc.py             |  4 ++--
 tests/gui/outside/__init__.py |  1 +
 8 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/anaconda b/anaconda
index 65a3d53..fcafcd6 100755
--- a/anaconda
+++ b/anaconda
@@ -969,7 +969,7 @@ if __name__ == "__main__":
         pidfile_created = True
         pid_string = "%s\n" % os.getpid()
         iutil.eintr_retry_call(os.write, pidfile, pid_string.encode("utf-8"))
-        os.close(pidfile)
+        iutil.eintr_ignore(os.close, pidfile)
     except FileExistsError:
         log.error("%s already exists, exiting", pidfile_path)
 
diff --git a/pyanaconda/anaconda.py b/pyanaconda/anaconda.py
index 89c28b2..8b75d62 100644
--- a/pyanaconda/anaconda.py
+++ b/pyanaconda/anaconda.py
@@ -203,7 +203,7 @@ def dumpState(self):
         dump_text += threads
         dump_text = dump_text.encode("utf-8")
         iutil.eintr_retry_call(os.write, fd, dump_text)
-        os.close(fd)
+        iutil.eintr_ignore(os.close, fd)
 
         # append to a given file
         with open("/tmp/anaconda-tb-all.log", "a+") as f:
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
index 4d3fa39..4819bd6 100644
--- a/pyanaconda/bootloader.py
+++ b/pyanaconda/bootloader.py
@@ -61,7 +61,7 @@ def get_boot_block(device, seek_blocks=0):
     if seek_blocks:
         os.lseek(fd, seek_blocks * block_size, 0)
     block = iutil.eintr_retry_call(os.read, fd, 512)
-    os.close(fd)
+    iutil.eintr_ignore(os.close, fd)
     if not status:
         try:
             device.teardown(recursive=True)
@@ -1347,11 +1347,11 @@ def install(self, args=None):
                       "stage2dev": self.grub_device_name(stage2dev)})
             (pread, pwrite) = os.pipe()
             iutil.eintr_retry_call(os.write, pwrite, cmd.encode("utf-8"))
-            os.close(pwrite)
+            iutil.eintr_ignore(os.close, pwrite)
             args = ["--batch", "--no-floppy",
                     "--device-map=%s" % self.device_map_file]
             rc = iutil.execInSysroot("grub", args, stdin=pread)
-            os.close(pread)
+            iutil.eintr_ignore(os.close, pread)
             if rc:
                 raise BootLoaderError("boot loader install failed")
 
@@ -1540,11 +1540,11 @@ def _encrypt_password(self):
         (pread, pwrite) = os.pipe()
         passwords = "%s\n%s\n" % (self.password, self.password)
         iutil.eintr_retry_call(os.write, pwrite, passwords.encode("utf-8"))
-        os.close(pwrite)
+        iutil.eintr_ignore(os.close, pwrite)
         buf = iutil.execWithCapture("grub2-mkpasswd-pbkdf2", [],
                                     stdin=pread,
                                     root=iutil.getSysroot())
-        os.close(pread)
+        iutil.eintr_ignore(os.close, pread)
         self.encrypted_password = buf.split()[-1].strip()
         if not self.encrypted_password.startswith("grub.pbkdf2."):
             raise BootLoaderError("failed to encrypt boot loader password")
diff --git a/pyanaconda/exception.py b/pyanaconda/exception.py
index 2fa3661..ab6b1e1 100644
--- a/pyanaconda/exception.py
+++ b/pyanaconda/exception.py
@@ -196,11 +196,11 @@ def runDebug(self, exc_info):
             iutil.vtActivate(1)
 
         iutil.eintr_retry_call(os.open, "/dev/console", os.O_RDWR)   # reclaim stdin
-        os.dup2(0, 1)                        # reclaim stdout
-        os.dup2(0, 2)                        # reclaim stderr
-        #   ^
-        #   |
-        #   +------ dup2 is magic, I tells ya!
+        iutil.eintr_ignore(os.dup2, 0, 1)                        # reclaim stdout
+        iutil.eintr_ignore(os.dup2, 0, 2)                        # reclaim stderr
+        #                      ^
+        #                      |
+        #                      +------ dup2 is magic, I tells ya!
 
         # bring back the echo
         import termios
diff --git a/pyanaconda/iutil.py b/pyanaconda/iutil.py
index ecd089a..fafa593 100644
--- a/pyanaconda/iutil.py
+++ b/pyanaconda/iutil.py
@@ -1287,7 +1287,7 @@ def ipmi_report(event):
     # Event data 2 & 3 - always 0x0 for us
     event_string = "0x4 0x1F 0x0 0x6f %#x 0x0 0x0\n" % event
     eintr_retry_call(os.write, fd, event_string.encode("utf-8"))
-    os.close(fd)
+    eintr_ignore(os.close, fd)
 
     execWithCapture("ipmitool", ["sel", "add", path])
 
@@ -1302,6 +1302,18 @@ def eintr_retry_call(func, *args, **kwargs):
         except InterruptedError:
             continue
 
+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 InterruptedError:
+        pass
+
 def parent_dir(directory):
     """Return the parent's path"""
     return "/".join(os.path.normpath(directory).split("/")[:-1])
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 8dcad54..804f729 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -105,7 +105,7 @@ def run(self, chroot):
         (fd, path) = tempfile.mkstemp("", "ks-script-", scriptRoot + "/tmp")
 
         iutil.eintr_retry_call(os.write, fd, self.script.encode("utf-8"))
-        os.close(fd)
+        iutil.eintr_ignore(os.close, fd)
         iutil.eintr_retry_call(os.chmod, path, 0o700)
 
         # Always log stdout/stderr from scripts.  Using --log just lets you
diff --git a/pyanaconda/vnc.py b/pyanaconda/vnc.py
index 7f1a7d3..0248f45 100644
--- a/pyanaconda/vnc.py
+++ b/pyanaconda/vnc.py
@@ -88,8 +88,8 @@ def setVNCPassword(self):
             rc = iutil.execWithRedirect("vncpasswd", ["-f"],
                     stdin=r, stdout=pw_file, binary_output=True, log_output=False)
 
-            os.close(r)
-            os.close(w)
+            iutil.eintr_ignore(os.close, r)
+            iutil.eintr_ignore(os.close, w)
 
         return rc
 
diff --git a/tests/gui/outside/__init__.py b/tests/gui/outside/__init__.py
index 3eba8d9..7b18cbf 100644
--- a/tests/gui/outside/__init__.py
+++ b/tests/gui/outside/__init__.py
@@ -19,6 +19,7 @@
 
 # Ignore any interruptible calls
 # pylint: disable=interruptible-system-call
+# pylint: disable=ignorable-system-call
 
 __all__ = ["Creator", "OutsideMixin"]
 


-- 
To view this commit on github, visit https://github.com/rhinstaller/anaconda/commit/f97feab7ac1f3a8518749ac5db89a27bf96a2995


More information about the anaconda-patches mailing list