From 280d8659601a5e3b8dab77231d9f9fc16f5cd1ce Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Fri, 4 Oct 2013 11:09:23 +0200 Subject: [PATCH 1/3] fix issue #879 and add a test for it Signed-off-by: Armin Ronacher --- flask/app.py | 2 +- flask/testsuite/basic.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/flask/app.py b/flask/app.py index c3170df6..cc3fc1d9 100644 --- a/flask/app.py +++ b/flask/app.py @@ -1492,9 +1492,9 @@ class Flask(_PackageBoundObject): with self._before_request_lock: if self._got_first_request: return - self._got_first_request = True for func in self.before_first_request_funcs: func() + self._got_first_request = True def make_default_options_response(self): """This method is called to create the default `OPTIONS` response. diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index 1858ca5c..8399a607 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -16,6 +16,7 @@ import pickle import unittest from datetime import datetime from threading import Thread +from time import sleep from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning from flask._compat import text_type from werkzeug.exceptions import BadRequest, NotFound @@ -1015,6 +1016,23 @@ class BasicFunctionalityTestCase(FlaskTestCase): self.assert_equal(got, [42]) self.assert_true(app.got_first_request) + def test_before_first_request_functions_concurrent(self): + got = [] + app = flask.Flask(__name__) + @app.before_first_request + def foo(): + sleep(1) + got.append(42) + c = app.test_client() + def get_and_assert(): + c.get("/") + self.assert_equal(got, [42]) + t = Thread(target=get_and_assert) + t.start() + get_and_assert() + t.join() + self.assert_true(app.got_first_request) + def test_routing_redirect_debugging(self): app = flask.Flask(__name__) app.debug = True From 75f2af7a6afdf620d7afdccee876b06f8c39373b Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 9 Feb 2014 13:25:36 +0000 Subject: [PATCH 2/3] Use a condition variable instead of sleeping --- flask/testsuite/basic.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/flask/testsuite/basic.py b/flask/testsuite/basic.py index 8399a607..4da4c549 100644 --- a/flask/testsuite/basic.py +++ b/flask/testsuite/basic.py @@ -15,8 +15,7 @@ import flask import pickle import unittest from datetime import datetime -from threading import Thread -from time import sleep +from threading import Thread, Condition from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning from flask._compat import text_type from werkzeug.exceptions import BadRequest, NotFound @@ -1019,12 +1018,16 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_before_first_request_functions_concurrent(self): got = [] app = flask.Flask(__name__) + cv = Condition() @app.before_first_request def foo(): - sleep(1) + with cv: + cv.wait() got.append(42) c = app.test_client() def get_and_assert(): + with cv: + cv.notify() c.get("/") self.assert_equal(got, [42]) t = Thread(target=get_and_assert) From 141a5533c97306525551dc215510735e5b50ae0b Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 9 Feb 2014 13:26:32 +0000 Subject: [PATCH 3/3] Documented fix for #879 --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index fc5831b5..a67937ff 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,9 @@ Version 0.10.2 - Fixed an etags bug when sending a file streams with a name. - Fixed `send_from_directory` not expanding to the application root path correctly. +- Changed logic of before first request handlers to flip the flag after + invoking. This will allow some uses that are potentially dangerous but + should probably be permitted. Version 0.10.1 --------------