Attempt to address crash bug when stopping threadpool if there are pending web requests. Return a DeferredList to be checked in server shutdown.
This commit is contained in:
parent
1248428d13
commit
4b5ee77292
2 changed files with 33 additions and 2 deletions
|
|
@ -151,7 +151,8 @@ class Evennia(object):
|
||||||
sys.path.insert(1, '.')
|
sys.path.insert(1, '.')
|
||||||
|
|
||||||
# create a store of services
|
# create a store of services
|
||||||
self.services = service.IServiceCollection(application)
|
self.services = service.MultiService()
|
||||||
|
self.services.setServiceParent(application)
|
||||||
self.amp_protocol = None # set by amp factory
|
self.amp_protocol = None # set by amp factory
|
||||||
self.sessions = SESSIONS
|
self.sessions = SESSIONS
|
||||||
self.sessions.server = self
|
self.sessions.server = self
|
||||||
|
|
@ -348,6 +349,10 @@ class Evennia(object):
|
||||||
from evennia.server.models import ServerConfig
|
from evennia.server.models import ServerConfig
|
||||||
from evennia.utils import gametime as _GAMETIME_MODULE
|
from evennia.utils import gametime as _GAMETIME_MODULE
|
||||||
|
|
||||||
|
if WEBSERVER_ENABLED:
|
||||||
|
# finish all pending web requests. Otherwise stopping threadpool will cause deadlock.
|
||||||
|
yield self.web_root.get_pending_requests()
|
||||||
|
|
||||||
if mode == 'reload':
|
if mode == 'reload':
|
||||||
# call restart hooks
|
# call restart hooks
|
||||||
ServerConfig.objects.conf("server_restart_mode", "reload")
|
ServerConfig.objects.conf("server_restart_mode", "reload")
|
||||||
|
|
@ -533,11 +538,13 @@ if WEBSERVER_ENABLED:
|
||||||
# recognized by Django
|
# recognized by Django
|
||||||
threads = threadpool.ThreadPool(minthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[0]),
|
threads = threadpool.ThreadPool(minthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[0]),
|
||||||
maxthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[1]))
|
maxthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[1]))
|
||||||
|
|
||||||
web_root = DjangoWebRoot(threads)
|
web_root = DjangoWebRoot(threads)
|
||||||
# point our media resources to url /media
|
# point our media resources to url /media
|
||||||
web_root.putChild("media", static.File(settings.MEDIA_ROOT))
|
web_root.putChild("media", static.File(settings.MEDIA_ROOT))
|
||||||
# point our static resources to url /static
|
# point our static resources to url /static
|
||||||
web_root.putChild("static", static.File(settings.STATIC_ROOT))
|
web_root.putChild("static", static.File(settings.STATIC_ROOT))
|
||||||
|
EVENNIA.web_root = web_root
|
||||||
|
|
||||||
if WEB_PLUGINS_MODULE:
|
if WEB_PLUGINS_MODULE:
|
||||||
# custom overloads
|
# custom overloads
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ from evennia.utils import logger
|
||||||
_UPSTREAM_IPS = settings.UPSTREAM_IPS
|
_UPSTREAM_IPS = settings.UPSTREAM_IPS
|
||||||
_DEBUG = settings.DEBUG
|
_DEBUG = settings.DEBUG
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# X-Forwarded-For Handler
|
# X-Forwarded-For Handler
|
||||||
#
|
#
|
||||||
|
|
@ -117,6 +118,8 @@ class DjangoWebRoot(resource.Resource):
|
||||||
understands by tweaking the way
|
understands by tweaking the way
|
||||||
child instancee ars recognized.
|
child instancee ars recognized.
|
||||||
"""
|
"""
|
||||||
|
open_requests = []
|
||||||
|
|
||||||
def __init__(self, pool):
|
def __init__(self, pool):
|
||||||
"""
|
"""
|
||||||
Setup the django+twisted resource.
|
Setup the django+twisted resource.
|
||||||
|
|
@ -128,6 +131,21 @@ class DjangoWebRoot(resource.Resource):
|
||||||
resource.Resource.__init__(self)
|
resource.Resource.__init__(self)
|
||||||
self.wsgi_resource = WSGIResource(reactor, pool, WSGIHandler())
|
self.wsgi_resource = WSGIResource(reactor, pool, WSGIHandler())
|
||||||
|
|
||||||
|
def get_pending_requests(self):
|
||||||
|
"""
|
||||||
|
Converts our open_requests list of deferreds into a DeferredList
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
d_list (deferred): A DeferredList object of all our requests
|
||||||
|
"""
|
||||||
|
from twisted.internet import defer
|
||||||
|
return defer.DeferredList(self.open_requests, consumeErrors=True)
|
||||||
|
|
||||||
|
def _decrement_requests(self, *args, **kwargs):
|
||||||
|
deferred = kwargs.get('deferred', None)
|
||||||
|
if deferred in self.open_requests:
|
||||||
|
self.open_requests.remove(deferred)
|
||||||
|
|
||||||
def getChild(self, path, request):
|
def getChild(self, path, request):
|
||||||
"""
|
"""
|
||||||
To make things work we nudge the url tree to make this the
|
To make things work we nudge the url tree to make this the
|
||||||
|
|
@ -140,8 +158,12 @@ class DjangoWebRoot(resource.Resource):
|
||||||
"""
|
"""
|
||||||
path0 = request.prepath.pop(0)
|
path0 = request.prepath.pop(0)
|
||||||
request.postpath.insert(0, path0)
|
request.postpath.insert(0, path0)
|
||||||
|
deferred = request.notifyFinish()
|
||||||
|
self.open_requests.append(deferred)
|
||||||
|
deferred.addBoth(self._decrement_requests, deferred=deferred)
|
||||||
return self.wsgi_resource
|
return self.wsgi_resource
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Site with deactivateable logging
|
# Site with deactivateable logging
|
||||||
#
|
#
|
||||||
|
|
@ -151,11 +173,13 @@ class Website(server.Site):
|
||||||
This class will only log http requests if settings.DEBUG is True.
|
This class will only log http requests if settings.DEBUG is True.
|
||||||
"""
|
"""
|
||||||
noisy = False
|
noisy = False
|
||||||
|
|
||||||
def log(self, request):
|
def log(self, request):
|
||||||
"Conditional logging"
|
"""Conditional logging"""
|
||||||
if _DEBUG:
|
if _DEBUG:
|
||||||
server.Site.log(self, request)
|
server.Site.log(self, request)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Threaded Webserver
|
# Threaded Webserver
|
||||||
#
|
#
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue