Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a warning when the wsgi server is multiprocess #286

Merged
merged 3 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ Unreleased
the top-level ``<li>`` tag has the id now.
See https://github.com/Pylons/pyramid_debugtoolbar/pull/285

- Emit a warning and disable the toolbar if the app is being served by
a forking / multiprocess wsgi server that sets
``environ['wsgi.multiprocess']`` to ``True``. This should help avoid
confusing issues in certain deployments like gunicorn and uwsgi multiprocess
modes. See https://github.com/Pylons/pyramid_debugtoolbar/pull/286

3.0.5 (2016-11-1)
-----------------

Expand Down
46 changes: 24 additions & 22 deletions demo/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from pyramid.httpexceptions import HTTPNotFound
from pyramid.session import UnencryptedCookieSessionFactoryConfig
from pyramid.session import SignedCookieSessionFactory
from pyramid.view import view_config
from wsgiref.simple_server import make_server

try:
import sqlalchemy
Expand Down Expand Up @@ -45,20 +44,20 @@ def exc(request):
def notfound(request):
raise HTTPNotFound()

@view_config(route_name='test_ajax', renderer='__main__:templates/ajax.mako')
@view_config(route_name='test_ajax', renderer='ajax.mako')
def test_ajax(request):
return {}

@view_config(route_name='call_ajax', renderer='json')
def call_ajax(request):
return {'ajax':'success'}

@view_config(context=HTTPNotFound, renderer='__main__:templates/notfound.mako')
@view_config(context=HTTPNotFound, renderer='notfound.mako')
def notfound_view(request):
request.response.status_code = 404
return {}

@view_config(renderer='__main__:templates/index.mako') # found via traversal
@view_config(renderer='index.mako') # found via traversal
def test_page(request):
title = 'Pyramid Debugtoolbar'
log.info(title)
Expand All @@ -72,21 +71,18 @@ def test_redirect(request):
return HTTPFound(location='/')

@view_config(route_name='test_highorder',
renderer='__main__:templates/highorder.mako')
renderer='highorder.mako')
def test_highorder(request):
return {}

@view_config(route_name='test_predicates',
renderer='__main__:templates/index.mako')
renderer='index.mako')
def test_predicates(request):
return {'title': 'Test route predicates'}

@view_config(route_name='test_chameleon_exc',
renderer='__main__:templates/error.pt')
@view_config(route_name='test_mako_exc',
renderer='__main__:templates/error.mako')
@view_config(route_name='test_jinja2_exc',
renderer='__main__:templates/error.jinja2')
@view_config(route_name='test_chameleon_exc', renderer='error.pt')
@view_config(route_name='test_mako_exc', renderer='error.mako')
@view_config(route_name='test_jinja2_exc', renderer='error.jinja2')
def test_template_exc(request):
return {'title': 'Test template exceptions'}

Expand All @@ -96,27 +92,28 @@ def __init__(self, request):
def __getitem__(self, name):
return self

if __name__ == '__main__':
def make_app():
# configuration settings
try:
# ease testing py2 and py3 in same directory
shutil.rmtree(os.path.join(here, 'mako_modules'))
except:
pass
settings = {}
settings['reload_templates'] = True
settings['mako.directories'] = '__main__:templates'
settings['mako.module_directory'] = '__main__:mako_modules'
settings['pyramid.reload_templates'] = True
settings['mako.directories'] = __name__ + ':templates'
settings['mako.module_directory'] = __name__ + ':mako_modules'
settings['debugtoolbar.reload_templates'] = True
settings['debugtoolbar.hosts'] = ['127.0.0.1']
settings['debugtoolbar.intercept_redirects'] = True
settings['debugtoolbar.exclude_prefixes'] = ['/static']

# session factory
session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
session_factory = SignedCookieSessionFactory('itsaseekreet')
# configuration setup
config = Configurator(settings=settings, session_factory=session_factory,
root_factory=DummyRootFactory)
config = Configurator(settings=settings)
config.set_session_factory(session_factory)
config.set_root_factory(DummyRootFactory)
# static view
config.add_static_view('static', os.path.join(here, 'static'))
# routes setup
Expand All @@ -130,14 +127,19 @@ def __getitem__(self, name):
config.add_route('test_highorder', text_(b'/La Pe\xc3\xb1a', 'utf-8'))
config.add_route('test_ajax', '/ajax')
config.add_route('call_ajax', '/call_ajax')
config.scan('__main__')
config.scan(__name__)
config.include('pyramid_chameleon')
config.include('pyramid_jinja2')
config.include('pyramid_mako')

if sqlalchemy:
config.include('sqla')
config.include('pyramid_debugtoolbar')
app = config.make_wsgi_app()
return config.make_wsgi_app()

app = make_app()

if __name__ == '__main__':
from wsgiref.simple_server import make_server
httpd = make_server('', 8080, app)
httpd.serve_forever()
2 changes: 1 addition & 1 deletion demo/sqla.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ def includeme(config):
initialize_sql(settings)

config.add_route('test_sqla', '/test_sqla')
config.scan('.')
config.scan(__name__)
9 changes: 9 additions & 0 deletions pyramid_debugtoolbar/toolbar.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import os
import warnings

from pyramid.exceptions import URLDecodeError
from pyramid.httpexceptions import WSGIHTTPException
Expand Down Expand Up @@ -186,6 +187,14 @@ def toolbar_tween(request):
):
return handler(request)

if request.environ.get('wsgi.multiprocess', False):
warnings.warn(
'pyramid_debugtoolbar has detected that the application is '
'being served by a forking / multiprocess web server. The '
'toolbar relies on global state to work and is not compatible '
'with this environment. The toolbar will be disabled.')
return handler(request)

root_path = debug_toolbar_url(request, '', _app_url='')
if p.startswith(root_path):
# we know root_path will always have a trailing slash
Expand Down