diff mbox series

[ovs-dev,python] Don't mix system poll/monkeypatched select

Message ID 20210611135339.443741-1-twilson@redhat.com
State Superseded
Headers show
Series [ovs-dev,python] Don't mix system poll/monkeypatched select | expand

Commit Message

Terry Wilson June 11, 2021, 1:53 p.m. UTC
This is a partial revert of c1aa16d19, but keeps its test.

Applications that use eventlet cannot use poll() without blocking.
To fix an issue where the check_connection_completion() code would
not detect connection errors when using select(), we switched to
using the system poll() for checking the connection while leaving
the select-based poller the default. This mixes monkeypatched and
unpatched code and caused eventlet-based code to block every time
we connect.

According to the connect(2) man page, you can detect connect()
errors when using select():

  After select(2) indicates writability, use getsockopt(2) to read
  the SO_ERROR option at level SOL_SOCKET to determine whether
  connect() completed successfully (SO_ERROR is zero) or
  unsuccessfully (SO_ERROR is one of the usual error codes listed
  here, explaining the reason for the failure)

so this patch does that instead.

Signed-off-by: Terry Wilson <twilson@redhat.com>
---
 python/ovs/poller.py      | 35 ++---------------------------------
 python/ovs/socket_util.py |  6 +++++-
 2 files changed, 7 insertions(+), 34 deletions(-)

Comments

0-day Robot June 11, 2021, 1:57 p.m. UTC | #1
Bleep bloop.  Greetings Terry Wilson, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


git-am:
error: sha1 information is lacking or useless (python/ovs/socket_util.py).
error: could not build fake ancestor
hint: Use 'git am --show-current-patch' to see the failed patch
Patch failed at 0001 Don't mix system poll/monkeypatched select
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
diff mbox series

Patch

diff --git a/python/ovs/poller.py b/python/ovs/poller.py
index 3624ec865..7b3238d6d 100644
--- a/python/ovs/poller.py
+++ b/python/ovs/poller.py
@@ -31,22 +31,14 @@  except ImportError:
     SSL = None
 
 try:
-    from eventlet import patcher as eventlet_patcher
+    import eventlet.patcher
 
     def _using_eventlet_green_select():
-        return eventlet_patcher.is_monkey_patched(select)
+        return eventlet.patcher.is_monkey_patched(select)
 except:
-    eventlet_patcher = None
-
     def _using_eventlet_green_select():
         return False
 
-try:
-    from gevent import monkey as gevent_monkey
-except:
-    gevent_monkey = None
-
-
 vlog = ovs.vlog.Vlog("poller")
 
 POLLIN = 0x001
@@ -265,26 +257,3 @@  class Poller(object):
     def __reset(self):
         self.poll = SelectPoll()
         self.timeout = -1
-
-
-def get_system_poll():
-    """Returns the original select.poll() object. If select.poll is
-    monkey patched by eventlet or gevent library, it gets the original
-    select.poll and returns an object of it using the
-    eventlet.patcher.original/gevent.monkey.get_original functions.
-
-    As a last resort, if there is any exception it returns the
-    SelectPoll() object.
-    """
-    try:
-        if _using_eventlet_green_select():
-            _system_poll = eventlet_patcher.original("select").poll
-        elif gevent_monkey and gevent_monkey.is_object_patched(
-                'select', 'poll'):
-            _system_poll = gevent_monkey.get_original('select', 'poll')
-        else:
-            _system_poll = select.poll
-    except:
-        _system_poll = SelectPoll
-
-    return _system_poll()
diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
index a73d6c6d7..0c322969a 100644
--- a/python/ovs/socket_util.py
+++ b/python/ovs/socket_util.py
@@ -174,7 +174,11 @@  def check_connection_completion(sock):
     pfds = p.poll(0)
     if len(pfds) == 1:
         revents = pfds[0][1]
-        if revents & ovs.poller.POLLERR or revents & ovs.poller.POLLHUP:
+        if revents & ovs.poller.POLLOUT:
+            # This is how select() indicates a connect() error
+            return sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
+        elif revents & ovs.poller.POLLERR or revents & ovs.poller.POLLHUP:
+            # This is how poll() indicates a connect() error
             try:
                 # The following should raise an exception.
                 sock.send("\0", socket.MSG_DONTWAIT)