Blame SOURCES/python-pyudev-0.15-retry-interrupted-calls.patch

fea5c0
diff --git a/pyudev/_util.py b/pyudev/_util.py
fea5c0
index 266b161..3ce82b2 100644
fea5c0
--- a/pyudev/_util.py
fea5c0
+++ b/pyudev/_util.py
fea5c0
@@ -32,6 +32,7 @@
fea5c0
 import os
fea5c0
 import sys
fea5c0
 import stat
fea5c0
+import errno
fea5c0
 
fea5c0
 
fea5c0
 if sys.version_info[0] == 2:
fea5c0
@@ -141,3 +142,37 @@ def get_device_type(filename):
fea5c0
         return 'block'
fea5c0
     else:
fea5c0
         raise ValueError('not a device file: {0!r}'.format(filename))
fea5c0
+
fea5c0
+
fea5c0
+def eintr_retry_call(func, *args, **kwargs):
fea5c0
+    """
fea5c0
+    Handle interruptions to an interruptible system call.
fea5c0
+
fea5c0
+    Run an interruptible system call in a loop and retry if it raises EINTR.
fea5c0
+    The signal calls that may raise EINTR prior to Python 3.5 are listed in
fea5c0
+    PEP 0475.  Any calls to these functions must be wrapped in eintr_retry_call
fea5c0
+    in order to handle EINTR returns in older versions of Python.
fea5c0
+
fea5c0
+    This function is safe to use under Python 3.5 and newer since the wrapped
fea5c0
+    function will simply return without raising EINTR.
fea5c0
+
fea5c0
+    This function is based on _eintr_retry_call in python's subprocess.py.
fea5c0
+    """
fea5c0
+
fea5c0
+    # select.error inherits from Exception instead of OSError in Python 2
fea5c0
+    import select
fea5c0
+
fea5c0
+    while True:
fea5c0
+        try:
fea5c0
+            return func(*args, **kwargs)
fea5c0
+        except (OSError, IOError, select.error) as e:
fea5c0
+            # If this is not an IOError or OSError, it's the old select.error
fea5c0
+            # type, which means that the errno is only accessible via subscript
fea5c0
+            if isinstance(e, (OSError, IOError)):
fea5c0
+                error_code = e.errno
fea5c0
+            else:
fea5c0
+                error_code = e.args[0]
fea5c0
+
fea5c0
+            if error_code == errno.EINTR:
fea5c0
+                continue
fea5c0
+            raise
fea5c0
diff --git a/pyudev/monitor.py b/pyudev/monitor.py
fea5c0
index b1eb71c..d87dc2c 100644
fea5c0
--- a/pyudev/monitor.py
fea5c0
+++ b/pyudev/monitor.py
fea5c0
@@ -36,7 +36,7 @@ import select
fea5c0
 from threading import Thread
fea5c0
 from contextlib import closing
fea5c0
 
fea5c0
-from pyudev._util import ensure_byte_string, ensure_unicode_string, reraise
fea5c0
+from pyudev._util import ensure_byte_string, ensure_unicode_string, reraise, eintr_retry_call
fea5c0
 
fea5c0
 from pyudev.core import Device
fea5c0
 
fea5c0
@@ -328,7 +328,7 @@ class Monitor(object):
fea5c0
         with closing(select.epoll()) as notifier:
fea5c0
             notifier.register(self, select.EPOLLIN)
fea5c0
             while True:
fea5c0
-                events = notifier.poll()
fea5c0
+                events = eintr_retry_call(notifier.poll)
fea5c0
                 for event in events:
fea5c0
                     yield self.receive_device()
fea5c0
 
fea5c0
@@ -399,7 +399,7 @@ class MonitorObserver(Thread):
fea5c0
             # and on the monitor
fea5c0
             notifier.register(self.monitor, select.EPOLLIN)
fea5c0
             while True:
fea5c0
-                for fd, _ in notifier.poll():
fea5c0
+                for fd, _ in eintr_retry_call(notifier.poll):
fea5c0
                     if fd == self._stop_event_source:
fea5c0
                         # in case of a stop event, close our pipe side, and
fea5c0
                         # return from the thread