monkeypatch thread for keystoneclient

keystoneclient uses threading.Lock(), but swift doesn't
monkeypatch threading, this result in lockup when two
greenthreads try to acquire a non green lock.

This change fixes that.

Change-Id: I9b44284a5eb598a6978364819f253e031f4eaeef
Closes-bug: #1508424
This commit is contained in:
Mehdi Abaakouk 2015-10-22 17:33:09 +02:00
parent e1910dff17
commit bf8689474a
7 changed files with 35 additions and 22 deletions

View File

@ -26,7 +26,6 @@ import os
import pwd import pwd
import re import re
import sys import sys
import threading as stdlib_threading
import time import time
import uuid import uuid
import functools import functools
@ -63,7 +62,6 @@ import six
from six.moves import cPickle as pickle from six.moves import cPickle as pickle
from six.moves.configparser import (ConfigParser, NoSectionError, from six.moves.configparser import (ConfigParser, NoSectionError,
NoOptionError, RawConfigParser) NoOptionError, RawConfigParser)
from six.moves.queue import Queue, Empty
from six.moves import range from six.moves import range
from six.moves.urllib.parse import ParseResult from six.moves.urllib.parse import ParseResult
from six.moves.urllib.parse import quote as _quote from six.moves.urllib.parse import quote as _quote
@ -74,6 +72,11 @@ import swift.common.exceptions
from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND, \ from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND, \
HTTP_PRECONDITION_FAILED, HTTP_REQUESTED_RANGE_NOT_SATISFIABLE HTTP_PRECONDITION_FAILED, HTTP_REQUESTED_RANGE_NOT_SATISFIABLE
if six.PY3:
stdlib_queue = eventlet.patcher.original('queue')
else:
stdlib_queue = eventlet.patcher.original('Queue')
stdlib_threading = eventlet.patcher.original('threading')
# logging doesn't import patched as cleanly as one would like # logging doesn't import patched as cleanly as one would like
from logging.handlers import SysLogHandler from logging.handlers import SysLogHandler
@ -2333,7 +2336,7 @@ class GreenAsyncPile(object):
def next(self): def next(self):
try: try:
rv = self._responses.get_nowait() rv = self._responses.get_nowait()
except Empty: except eventlet.queue.Empty:
if self._inflight == 0: if self._inflight == 0:
raise StopIteration() raise StopIteration()
rv = self._responses.get() rv = self._responses.get()
@ -2984,8 +2987,8 @@ class ThreadPool(object):
def __init__(self, nthreads=2): def __init__(self, nthreads=2):
self.nthreads = nthreads self.nthreads = nthreads
self._run_queue = Queue() self._run_queue = stdlib_queue.Queue()
self._result_queue = Queue() self._result_queue = stdlib_queue.Queue()
self._threads = [] self._threads = []
self._alive = True self._alive = True
@ -3065,7 +3068,7 @@ class ThreadPool(object):
while True: while True:
try: try:
ev, success, result = queue.get(block=False) ev, success, result = queue.get(block=False)
except Empty: except stdlib_queue.Empty:
break break
try: try:

View File

@ -407,7 +407,8 @@ def run_server(conf, logger, sock, global_conf=None):
wsgi.WRITE_TIMEOUT = int(conf.get('client_timeout') or 60) wsgi.WRITE_TIMEOUT = int(conf.get('client_timeout') or 60)
eventlet.hubs.use_hub(get_hub()) eventlet.hubs.use_hub(get_hub())
eventlet.patcher.monkey_patch(all=False, socket=True) # NOTE(sileht): monkey-patching thread is required by python-keystoneclient
eventlet.patcher.monkey_patch(all=False, socket=True, thread=True)
eventlet_debug = config_true_value(conf.get('eventlet_debug', 'no')) eventlet_debug = config_true_value(conf.get('eventlet_debug', 'no'))
eventlet.debug.hub_exceptions(eventlet_debug) eventlet.debug.hub_exceptions(eventlet_debug)
wsgi_logger = NullLogger() wsgi_logger = NullLogger()

View File

@ -18,7 +18,6 @@ import time
import eventlet import eventlet
import mock import mock
from contextlib import contextmanager from contextlib import contextmanager
from threading import Thread
from test.unit import FakeLogger from test.unit import FakeLogger
from swift.common.middleware import ratelimit from swift.common.middleware import ratelimit
@ -28,6 +27,8 @@ from swift.common.memcached import MemcacheConnectionError
from swift.common.swob import Request from swift.common.swob import Request
from swift.common import utils from swift.common import utils
threading = eventlet.patcher.original('threading')
class FakeMemcache(object): class FakeMemcache(object):
@ -313,10 +314,10 @@ class TestRateLimit(unittest.TestCase):
req = Request.blank('/v/a/c') req = Request.blank('/v/a/c')
req.environ['swift.cache'] = FakeMemcache() req.environ['swift.cache'] = FakeMemcache()
class rate_caller(Thread): class rate_caller(threading.Thread):
def __init__(self, parent): def __init__(self, parent):
Thread.__init__(self) threading.Thread.__init__(self)
self.parent = parent self.parent = parent
def run(self): def run(self):
@ -356,10 +357,10 @@ class TestRateLimit(unittest.TestCase):
req = Request.blank('/v/b/c') req = Request.blank('/v/b/c')
req.environ['swift.cache'] = FakeMemcache() req.environ['swift.cache'] = FakeMemcache()
class rate_caller(Thread): class rate_caller(threading.Thread):
def __init__(self, parent): def __init__(self, parent):
Thread.__init__(self) threading.Thread.__init__(self)
self.parent = parent self.parent = parent
def run(self): def run(self):
@ -505,11 +506,11 @@ class TestRateLimit(unittest.TestCase):
req.method = 'PUT' req.method = 'PUT'
req.environ = {} req.environ = {}
class rate_caller(Thread): class rate_caller(threading.Thread):
def __init__(self, name): def __init__(self, name):
self.myname = name self.myname = name
Thread.__init__(self) threading.Thread.__init__(self)
def run(self): def run(self):
for j in range(num_calls): for j in range(num_calls):

View File

@ -22,12 +22,14 @@ import resource
import signal import signal
import errno import errno
from collections import defaultdict from collections import defaultdict
from threading import Thread
from time import sleep, time from time import sleep, time
from swift.common import manager from swift.common import manager
from swift.common.exceptions import InvalidPidFileException from swift.common.exceptions import InvalidPidFileException
import eventlet
threading = eventlet.patcher.original('threading')
DUMMY_SIG = 1 DUMMY_SIG = 1
@ -1153,9 +1155,9 @@ class TestServer(unittest.TestCase):
server = manager.Server('test') server = manager.Server('test')
self.assertEqual(server.wait(), 0) self.assertEqual(server.wait(), 0)
class MockProcess(Thread): class MockProcess(threading.Thread):
def __init__(self, delay=0.1, fail_to_start=False): def __init__(self, delay=0.1, fail_to_start=False):
Thread.__init__(self) threading.Thread.__init__(self)
# setup pipe # setup pipe
rfd, wfd = os.pipe() rfd, wfd = os.pipe()
# subprocess connection to read stdout # subprocess connection to read stdout

View File

@ -40,7 +40,6 @@ from six.moves import range
from textwrap import dedent from textwrap import dedent
import tempfile import tempfile
import threading
import time import time
import traceback import traceback
import unittest import unittest
@ -64,6 +63,8 @@ from swift.common.container_sync_realms import ContainerSyncRealms
from swift.common.swob import Request, Response, HeaderKeyDict from swift.common.swob import Request, Response, HeaderKeyDict
from test.unit import FakeLogger from test.unit import FakeLogger
threading = eventlet.patcher.original('threading')
class MockOs(object): class MockOs(object):

View File

@ -380,7 +380,8 @@ class TestWSGI(unittest.TestCase):
self.assertEqual(30, _wsgi.WRITE_TIMEOUT) self.assertEqual(30, _wsgi.WRITE_TIMEOUT)
_eventlet.hubs.use_hub.assert_called_with(utils.get_hub()) _eventlet.hubs.use_hub.assert_called_with(utils.get_hub())
_eventlet.patcher.monkey_patch.assert_called_with(all=False, _eventlet.patcher.monkey_patch.assert_called_with(all=False,
socket=True) socket=True,
thread=True)
_eventlet.debug.hub_exceptions.assert_called_with(False) _eventlet.debug.hub_exceptions.assert_called_with(False)
self.assertTrue(_wsgi.server.called) self.assertTrue(_wsgi.server.called)
args, kwargs = _wsgi.server.call_args args, kwargs = _wsgi.server.call_args
@ -468,7 +469,8 @@ class TestWSGI(unittest.TestCase):
self.assertEqual(30, _wsgi.WRITE_TIMEOUT) self.assertEqual(30, _wsgi.WRITE_TIMEOUT)
_eventlet.hubs.use_hub.assert_called_with(utils.get_hub()) _eventlet.hubs.use_hub.assert_called_with(utils.get_hub())
_eventlet.patcher.monkey_patch.assert_called_with(all=False, _eventlet.patcher.monkey_patch.assert_called_with(all=False,
socket=True) socket=True,
thread=True)
_eventlet.debug.hub_exceptions.assert_called_with(False) _eventlet.debug.hub_exceptions.assert_called_with(False)
self.assertTrue(_wsgi.server.called) self.assertTrue(_wsgi.server.called)
args, kwargs = _wsgi.server.call_args args, kwargs = _wsgi.server.call_args
@ -519,7 +521,8 @@ class TestWSGI(unittest.TestCase):
self.assertEqual(30, _wsgi.WRITE_TIMEOUT) self.assertEqual(30, _wsgi.WRITE_TIMEOUT)
_eventlet.hubs.use_hub.assert_called_with(utils.get_hub()) _eventlet.hubs.use_hub.assert_called_with(utils.get_hub())
_eventlet.patcher.monkey_patch.assert_called_with(all=False, _eventlet.patcher.monkey_patch.assert_called_with(all=False,
socket=True) socket=True,
thread=True)
_eventlet.debug.hub_exceptions.assert_called_with(True) _eventlet.debug.hub_exceptions.assert_called_with(True)
self.assertTrue(mock_server.called) self.assertTrue(mock_server.called)
args, kwargs = mock_server.call_args args, kwargs = mock_server.call_args

View File

@ -16,10 +16,12 @@
# limitations under the License. # limitations under the License.
from __future__ import print_function from __future__ import print_function
import eventlet
import os import os
import unittest import unittest
import sys import sys
import threading
threading = eventlet.patcher.original('threading')
try: try:
from subprocess import check_output from subprocess import check_output