Browse Source

Fix AttributeError on select.poll()

Change-Id: Iefcae89cdedd13535c3135ca7227362f1cf9abc8
Closes-Bug: #1889396
Co-Authored-By: Mitchell Jameson <>
Aurelien Lourot 2 months ago
committed by Mitchell Jameson
1 changed files with 42 additions and 2 deletions
  1. +42

+ 42
- 2
networking_arista/ml2/ View File

@@ -14,7 +14,6 @@
# limitations under the License.

import json
from multiprocessing import Queue

from neutron_lib.api.definitions import portbindings
from neutron_lib import constants as n_const
@@ -32,6 +31,47 @@ from networking_arista.ml2 import arista_sync
from networking_arista.ml2 import arista_trunk
from networking_arista.ml2.rpc.arista_eapi import AristaRPCWrapperEapi

# When used as a Neutron plugin, neutron-lib imports this code. However earlier
# neutron-lib has already imported 'multiprocessing'. This means the python
# module cache (sys.modules) contains a version of 'multiprocessing' where
# select.poll() exists.
# Further down we import arista_sync, which spawns a greenthread. This
# greenthread then uses a green version of 'multiprocessing' where
# select.poll() has been removed.
# Doing here multiprocessing.Queue.put() and in the greenthread
# multiprocessing.Queue.get(timeout=...) leads to:
# AttributeError: module 'select' has no attribute 'poll'
# We can't do eventlet.monkey_patch() early enough (before the first
# 'mutiprocessing' import) as we would have to do it in neutron-lib and it's
# forbidden, see
# The solution is to let the python module cache here forget the already
# imported 'multiprocessing' and re-import a green one. Here again
# eventlet.monkey_patch() doesn't seem to help as it doesn't seem to touch
# 'multiprocessing'. Thus we use eventlet.import_patched() instead:
import eventlet
import sys
modules_to_forget = []
for imported_module_name in sys.modules:
if imported_module_name.startswith('multiprocessing'):
for module_to_forget in modules_to_forget:
del sys.modules[module_to_forget]

for module_to_forget in modules_to_forget:
except ImportError:

# import a green 'multiprocessing':
multiprocessing = eventlet.import_patched('multiprocessing')
from networking_arista.ml2 import arista_sync # noqa: E402

LOG = logging.getLogger(__name__)
cfg.CONF.import_group('ml2_arista', 'networking_arista.common.config')

@@ -69,7 +109,7 @@ class AristaDriver(driver_api.MechanismDriver):
self.eapi = AristaRPCWrapperEapi()
self.mlag_pairs = dict()

self.provision_queue = Queue()
self.provision_queue = multiprocessing.Queue()
self.trunk_driver = None

def initialize(self):