Merge "Avoid eventlet_backdoor listing on same port"

This commit is contained in:
Zuul 2019-01-17 13:52:22 +00:00 committed by Gerrit Code Review
commit 3c645a77ec
2 changed files with 25 additions and 4 deletions

View File

@ -21,13 +21,13 @@ import gc
import logging
import os
import pprint
import socket
import sys
import traceback
import eventlet.backdoor
import greenlet
from eventlet.green import socket
from oslo_service._i18n import _
from oslo_service import _options
@ -121,11 +121,24 @@ def _parse_port_range(port_range):
port_range, ex, _options.help_for_backdoor_port)
def _listen(host, start_port, end_port, listen_func):
def _listen_func(host, port):
# eventlet is setting SO_REUSEPORT by default from v0.20.
# But we can configure it by passing reuse_port argument
# from v0.22
try:
return eventlet.listen((host, port), reuse_port=False)
except TypeError:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(50)
return sock
def _listen(host, start_port, end_port):
try_port = start_port
while True:
try:
return listen_func((host, try_port))
return _listen_func(host, try_port)
except socket.error as exc:
if (exc.errno != errno.EADDRINUSE or
try_port >= end_port):
@ -169,7 +182,7 @@ def _initialize_if_enabled(conf):
if conf.backdoor_socket is None:
start_port, end_port = _parse_port_range(str(conf.backdoor_port))
sock = _listen('localhost', start_port, end_port, eventlet.listen)
sock = _listen('localhost', start_port, end_port)
# In the case of backdoor port being zero, a port number is assigned by
# listen(). In any case, pull the port number out here.
where_running = sock.getsockname()[1]

View File

@ -105,6 +105,14 @@ class BackdoorPortTest(base.ServiceBaseTestCase):
self.assertRaises(socket.error,
eventlet_backdoor.initialize_if_enabled, self.conf)
@mock.patch.object(eventlet, 'spawn')
def test_backdoor_port_range_inuse(self, spawn_mock):
self.config(backdoor_port='8800:8801')
port = eventlet_backdoor.initialize_if_enabled(self.conf)
self.assertEqual(8800, port)
port = eventlet_backdoor.initialize_if_enabled(self.conf)
self.assertEqual(8801, port)
@mock.patch.object(eventlet, 'spawn')
@mock.patch.object(eventlet, 'listen')
def test_backdoor_port_range(self, listen_mock, spawn_mock):