Skip to content

Commit 149198e

Browse files
Merge branch 'release/4.5.21'
2 parents 1c50749 + 2748873 commit 149198e

File tree

9 files changed

+101
-6
lines changed

9 files changed

+101
-6
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ MacOS X Sierra, the System Integrity Protection (SIP) system of MacOS X,
359359
prevented installing the mod_wsgi module into the Apache modules directory.
360360

361361
If you are using Windows, the CMMI method was never supported as Windows
362-
doesn't supply the required tools tools to make it work.
362+
doesn't supply the required tools to make it work.
363363

364364
The CMMI installation method also involves a bit more work as you need to
365365
separately download the mod_wsgi source code, run the ``configure`` tool

docs/release-notes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Release Notes
55
.. toctree::
66
:maxdepth: 2
77

8+
release-notes/version-4.5.21
89
release-notes/version-4.5.20
910
release-notes/version-4.5.19
1011
release-notes/version-4.5.18
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
==============
2+
Version 4.5.21
3+
==============
4+
5+
Version 4.5.21 of mod_wsgi can be obtained from:
6+
7+
https://codeload.github.com/GrahamDumpleton/mod_wsgi/tar.gz/4.5.21
8+
9+
Bugs Fixed
10+
----------
11+
12+
* Installation using ``pip`` or ``setup.py`` install was failing on
13+
MacOS X High Sierra with latest Xcode as Apple doesn't even include
14+
the ``apxs`` program at all.
15+
16+
Note you still cannot use the configure/make/make install method of
17+
deploying mod_wsgi to MacOS X. You need to use the ``pip install``
18+
method.
19+
20+
* Speculated that crashes on daemon process shutdown were being caused
21+
by a race condition around accessing Python C API when interpreter
22+
was being destroyed. There was a check in place to avoid this but may
23+
not have been robust enough depending on how memory cache worked
24+
for threads running across multi core machine. Now use a dedicated
25+
thread mutex to avoid race condition between main process thread and
26+
Python interpreter deadlock detection thread.
27+
28+
Features Changed
29+
----------------
30+
31+
* Set ``wsgi.input_terminated`` to ``True`` in WSGI environment. This is a
32+
unofficial extension to WSGI specification proposed by Armin Ronacher
33+
for a WSGI server/middleware to flag that it is safe to read to the
34+
end of input and that ``CONTENT_LENGTH`` can be ignored. This is to be
35+
able to support chunked request content, but also anything which
36+
mutates the request content length but which can't easily change the
37+
``CONTENT_LENGTH``, such as occurs when request content is compressed
38+
and is decompressed by the Apache web server.
39+
40+
The ability to safely read until end of input was always present in
41+
mod_wsgi, but there was no way in the WSGI specification for a WSGI
42+
server to tell a WSGI application this was the case. Prior attempts to
43+
include something to deal with this in the WSGI specification when it
44+
was updated in PEP 3333 were ignored. This is why now an unofficial way
45+
of doing it is being adopted by WSGI servers separate to the WSGI
46+
specification.

setup.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ def find_program(names, default=None, paths=[]):
133133

134134
WITHOUT_APXS = False
135135
WITH_WINDOWS_APACHE = None
136+
WITH_MACOSX_APACHE = None
136137

137138
if not WITH_TARBALL_PACKAGE:
138139
if not os.path.isabs(APXS) or not os.access(APXS, os.X_OK):
@@ -157,7 +158,10 @@ def find_program(names, default=None, paths=[]):
157158
raise RuntimeError('No Apache installation can be found. Set the '
158159
'MOD_WSGI_APACHE_ROOTDIR environment to its location.')
159160

160-
if WITHOUT_APXS and not WITH_WINDOWS_APACHE:
161+
elif WITHOUT_APXS and sys.platform == 'darwin':
162+
WITH_MACOSX_APACHE = '/Applications/Xcode.app'
163+
164+
if WITHOUT_APXS and not WITH_WINDOWS_APACHE and not WITHOUT_APXS:
161165
raise RuntimeError('The %r command appears not to be installed or '
162166
'is not executable. Please check the list of prerequisites '
163167
'in the documentation for this package and install any '
@@ -178,6 +182,27 @@ def get_apr_includes():
178182
def get_apu_includes():
179183
return ''
180184

185+
elif WITH_MACOSX_APACHE:
186+
def get_apxs_config(name):
187+
if name == 'BINDIR':
188+
return '/usr/bin'
189+
elif name == 'SBINDIR':
190+
return '/usr/sbin'
191+
elif name == 'LIBEXECDIR':
192+
return '/usr/libexec/apache2'
193+
elif name == 'PROGNAME':
194+
return 'httpd'
195+
elif name == 'SHLIBPATH_VAR':
196+
return 'DYLD_LIBRARY_PATH'
197+
else:
198+
return ''
199+
200+
def get_apr_includes():
201+
return ''
202+
203+
def get_apu_includes():
204+
return ''
205+
181206
elif WITH_TARBALL_PACKAGE:
182207
SCRIPT_DIR = os.path.join(os.path.dirname(__file__), 'src', 'packages')
183208

src/server/mod_wsgi.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static apr_array_header_t *wsgi_daemon_list = NULL;
7878

7979
static apr_pool_t *wsgi_parent_pool = NULL;
8080

81-
static int volatile wsgi_daemon_shutdown = 0;
81+
int volatile wsgi_daemon_shutdown = 0;
8282
static int volatile wsgi_daemon_graceful = 0;
8383

8484
#if defined(MOD_WSGI_WITH_DAEMONS)
@@ -2708,6 +2708,8 @@ static PyObject *Adapter_environ(AdapterObject *self)
27082708
object = (PyObject *)self->input;
27092709
PyDict_SetItemString(vars, "wsgi.input", object);
27102710

2711+
PyDict_SetItemString(vars, "wsgi.input_terminated", Py_True);
2712+
27112713
/* Setup file wrapper object for efficient file responses. */
27122714

27132715
PyDict_SetItemString(vars, "wsgi.file_wrapper", (PyObject *)&Stream_Type);
@@ -4286,6 +4288,7 @@ static void wsgi_python_child_init(apr_pool_t *p)
42864288
#if APR_HAS_THREADS
42874289
apr_thread_mutex_create(&wsgi_interp_lock, APR_THREAD_MUTEX_UNNESTED, p);
42884290
apr_thread_mutex_create(&wsgi_module_lock, APR_THREAD_MUTEX_UNNESTED, p);
4291+
apr_thread_mutex_create(&wsgi_shutdown_lock, APR_THREAD_MUTEX_UNNESTED, p);
42894292
#endif
42904293

42914294
/*
@@ -8952,11 +8955,15 @@ static void *wsgi_deadlock_thread(apr_thread_t *thd, void *data)
89528955
while (1) {
89538956
apr_sleep(apr_time_from_sec(1));
89548957

8958+
apr_thread_mutex_lock(wsgi_shutdown_lock);
8959+
89558960
if (!wsgi_daemon_shutdown) {
89568961
gilstate = PyGILState_Ensure();
89578962
PyGILState_Release(gilstate);
89588963
}
89598964

8965+
apr_thread_mutex_unlock(wsgi_shutdown_lock);
8966+
89608967
apr_thread_mutex_lock(wsgi_monitor_lock);
89618968
wsgi_deadlock_shutdown_time = apr_time_now();
89628969
wsgi_deadlock_shutdown_time += wsgi_deadlock_timeout;

src/server/wsgi_daemon.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ extern WSGIDaemonThread *wsgi_worker_threads;
185185

186186
extern WSGIThreadStack *wsgi_worker_stack;
187187

188+
extern int volatile wsgi_daemon_shutdown;
189+
188190
#endif
189191

190192
/* ------------------------------------------------------------------------- */

src/server/wsgi_interp.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1986,10 +1986,22 @@ apr_status_t wsgi_python_term(void)
19861986
if (!PyImport_AddModule("dummy_threading"))
19871987
PyErr_Clear();
19881988

1989-
/* Shutdown Python interpreter completely. */
1989+
/*
1990+
* Shutdown Python interpreter completely. Just to be safe
1991+
* flag daemon shutdown here again and do it within a lock
1992+
* which is then shared with deadlock thread used for the
1993+
* daemon. This is just to avoid any risk there is a race
1994+
* condition.
1995+
*/
1996+
1997+
apr_thread_mutex_lock(wsgi_shutdown_lock);
1998+
1999+
wsgi_daemon_shutdown++;
19902000

19912001
Py_Finalize();
19922002

2003+
apr_thread_mutex_unlock(wsgi_shutdown_lock);
2004+
19932005
wsgi_python_initialized = 0;
19942006

19952007
ap_log_error(APLOG_MARK, APLOG_INFO, 0, wsgi_server,
@@ -2336,6 +2348,7 @@ void wsgi_python_init(apr_pool_t *p)
23362348

23372349
#if APR_HAS_THREADS
23382350
apr_thread_mutex_t* wsgi_interp_lock = NULL;
2351+
apr_thread_mutex_t* wsgi_shutdown_lock = NULL;
23392352
#endif
23402353

23412354
PyObject *wsgi_interpreters = NULL;

src/server/wsgi_interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ extern PyObject *wsgi_interpreters;
7070

7171
#if APR_HAS_THREADS
7272
extern apr_thread_mutex_t *wsgi_interp_lock;
73+
extern apr_thread_mutex_t* wsgi_shutdown_lock;
7374
#endif
7475

7576
extern void wsgi_python_version(void);

src/server/wsgi_version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525

2626
#define MOD_WSGI_MAJORVERSION_NUMBER 4
2727
#define MOD_WSGI_MINORVERSION_NUMBER 5
28-
#define MOD_WSGI_MICROVERSION_NUMBER 20
29-
#define MOD_WSGI_VERSION_STRING "4.5.20"
28+
#define MOD_WSGI_MICROVERSION_NUMBER 21
29+
#define MOD_WSGI_VERSION_STRING "4.5.21"
3030

3131
/* ------------------------------------------------------------------------- */
3232

0 commit comments

Comments
 (0)