Undo the eventlet monkey patch for the privileged daemon

Change-Id: I422125b137a3beadb0a79f5944a19fce62f093d6
Closes-Bug: #1887506
This commit is contained in:
Rodolfo Alonso Hernandez 2020-07-14 13:51:07 +00:00
parent 071ab48007
commit 1dc378c76f
5 changed files with 77 additions and 2 deletions

View File

@ -6,7 +6,7 @@ cffi==1.7.0
debtcollector==1.2.0
docutils==0.11
dulwich==0.15.0
eventlet==0.18.2
eventlet==0.21.0
extras==1.0.0
fixtures==3.0.0
gitdb==0.6.4

View File

@ -57,6 +57,7 @@ import tempfile
import threading
import eventlet
from eventlet import patcher
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import encodeutils
@ -75,6 +76,25 @@ if platform.system() == 'Linux':
LOG = logging.getLogger(__name__)
EVENTLET_MODULES = ('os', 'select', 'socket', 'thread', 'time', 'MySQLdb',
'builtins', 'subprocess')
EVENTLET_LIBRARIES = []
def _null():
return []
for module in EVENTLET_MODULES:
if hasattr(patcher, '_green_%s_modules' % module):
method = getattr(patcher, '_green_%s_modules' % module)
elif hasattr(patcher, '_green_%s' % module):
method = getattr(patcher, '_green_%s' % module)
else:
method = _null()
EVENTLET_LIBRARIES.append((module, method))
@enum.unique
class StdioFd(enum.IntEnum):
# NOTE(gus): We can't use sys.std*.fileno() here. sys.std*
@ -258,6 +278,21 @@ def replace_logging(handler, log_root=None):
log_root.addHandler(handler)
def un_monkey_patch():
for eventlet_mod_name, func_modules in EVENTLET_LIBRARIES:
if not eventlet.patcher.is_monkey_patched(eventlet_mod_name):
continue
for name, mod in func_modules():
patched_mod = sys.modules.get(name)
orig_mod = eventlet.patcher.original(name)
for attr_name in mod.__patched__:
patched_attr = getattr(mod, attr_name, None)
unpatched_attr = getattr(orig_mod, attr_name, None)
if patched_attr is not None:
setattr(patched_mod, attr_name, unpatched_attr)
class ForkingClientChannel(_ClientChannel):
def __init__(self, context):
"""Start privsep daemon using fork()
@ -279,6 +314,7 @@ class ForkingClientChannel(_ClientChannel):
if os.fork() == 0:
# child
un_monkey_patch()
channel = comm.ServerChannel(sock_b)
sock_a.close()

View File

@ -13,6 +13,7 @@
# under the License.
import copy
import eventlet
import fixtures
import functools
import logging as pylogging
@ -215,3 +216,30 @@ class ClientChannelTestCase(base.BaseTestCase):
with mock.patch.object(daemon.LOG, 'warning') as mock_warning:
self.client_channel.out_of_band([daemon.Message.PING])
mock_warning.assert_called_once()
class UnMonkeyPatch(base.BaseTestCase):
def test_un_monkey_patch(self):
self.assertFalse(any(
eventlet.patcher.is_monkey_patched(eventlet_mod_name)
for eventlet_mod_name in daemon.EVENTLET_MODULES))
eventlet.monkey_patch()
self.assertTrue(any(
eventlet.patcher.is_monkey_patched(eventlet_mod_name)
for eventlet_mod_name in daemon.EVENTLET_MODULES))
daemon.un_monkey_patch()
for eventlet_mod_name, func_modules in daemon.EVENTLET_LIBRARIES:
if not eventlet.patcher.is_monkey_patched(eventlet_mod_name):
continue
for name, green_mod in func_modules():
orig_mod = eventlet.patcher.original(name)
patched_mod = sys.modules.get(name)
for attr_name in green_mod.__patched__:
un_monkey_patched_attr = getattr(patched_mod, attr_name,
None)
original_attr = getattr(orig_mod, attr_name, None)
self.assertEqual(un_monkey_patched_attr, original_attr)

View File

@ -0,0 +1,11 @@
---
other:
- |
The ``oslo.privsep`` client can be called from a program using eventlet.
If ``eventlet.monkey_patch``, some libraries will be patched, for example
``threading`` or ``os``. When the root daemon is forked from the client
process, those libraries remain patched. Now, when the daemon is forked
from the client process, those libraries and methods are restored to the
original values. The goal is to prevent some timeouts when using eventlet
threads (user threads); system threads are preemptive and the code does
not need to care about the executor token.

View File

@ -7,6 +7,6 @@ oslo.i18n>=3.15.3 # Apache-2.0
oslo.config>=5.2.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
cffi>=1.7.0 # MIT
eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT
eventlet>=0.21.0 # MIT
greenlet>=0.4.14 # MIT
msgpack>=0.6.0 # Apache-2.0