Skip to content

Commit ed155b3

Browse files
Merge branch 'release/4.4.11'
2 parents 830e6f5 + 9d24e44 commit ed155b3

File tree

7 files changed

+180
-24
lines changed

7 files changed

+180
-24
lines changed

README.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,15 +296,3 @@ agent configuration file.
296296
export NEW_RELIC_CONFIG_FILE
297297

298298
mod_wsgi-express start-server wsgi.py --with-newrelic
299-
300-
When using this option, if you have also installed the ``mod_wsgi-metrics``
301-
Python package, then additional metrics about Apache and mod_wsgi will also
302-
be reported via the New Relic Platform API. These will appear as a separate
303-
set of dashboards under 'mod_wsgi' in the left hand side navigation bar of
304-
the New Relic UI.
305-
306-
New Relic provides a free Lite tier so there is no excuse for not using it.
307-
Learn about what your Python web application is really doing. [1]_
308-
309-
.. [1] Disclaimer: I work for New Relic and am the primary developer of
310-
the Python agent. So of course it is awesome. :-)

docs/release-notes/index.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+
version-4.4.11.rst
89
version-4.4.10.rst
910
version-4.4.9.rst
1011
version-4.4.8.rst

docs/release-notes/version-4.4.11.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
==============
2+
Version 4.4.11
3+
==============
4+
5+
Version 4.4.11 of mod_wsgi can be obtained from:
6+
7+
https://codeload.github.com/GrahamDumpleton/mod_wsgi/tar.gz/4.4.11
8+
9+
For details on the availability of Windows binaries see:
10+
11+
https://github.com/GrahamDumpleton/mod_wsgi/tree/master/win32
12+
13+
Bugs Fixed
14+
----------
15+
16+
1. No provision was made for operating systems with a very low limit on the
17+
number of separate data blocks that could be passed to system ``writev()``
18+
call. This was an issue on Solaris where the limit is 16 and meant that since
19+
version 4.4.0, daemon mode of mod_wsgi would fail where a HTTP request had
20+
more than a small number of headers.
21+
22+
2. When installing the ``mod_wsgi`` package using ``pip`` and rather
23+
than activating the virtual environment you were referring to ``pip`` by
24+
path from the ``bin`` directory, the ``mod_wsgi-httpd`` package which
25+
had already been installed into the virtual environment would not be
26+
detected.
27+
28+
New Features
29+
------------
30+
31+
1. Added the ``--service-log`` option to ``mod_wsgi-express`` for
32+
specifying the name of a log file for a specific service script. The
33+
arguments are the name of the service and the file name for the log. The
34+
log file will be placed in the log directory, be it the default, or a
35+
specific log directory if specified.
36+
37+
2. Set various environment variables from ``mod_wsgi-express`` to identify
38+
that it is being used, what hosts it is handling requests for, and whether
39+
debug mode and/or specific debug mode features are enabled. This is so that
40+
a web application can modify it's behaviour when ``mod_wsgi-express`` is
41+
being used, or being used in specific ways. The environment variables which
42+
are set are:
43+
44+
* *MOD_WSGI_EXPRESS* - Indicates that ``mod_wsgi-express`` is being used.
45+
* *MOD_WSGI_SERVER_NAME* - The primary server host name for the site.
46+
* *MOD_WSGI_SERVER_ALIASES* - Secondary host names the site is known by.
47+
* *MOD_WSGI_RELOADER_ENABLED* - Indicates if source code reloading enabled.
48+
* *MOD_WSGI_DEBUG_MODE* - Indicates if debug mode has been enabled.
49+
* *MOD_WSGI_DEBUGGER_ENABLED* - Indicates pdb debugger has been enabled.
50+
* *MOD_WSGI_COVERAGE_ENABLED* - Indicates if coverage analysis has been
51+
enabled.
52+
* *MOD_WSGI_PROFILER_ENABLED* - Indicates if code profiling has been enabled.
53+
* *MOD_WSGI_RECORDER_ENABLED* - Indicates if request/response recording
54+
enabled.
55+
* *MOD_WSGI_GDB_ENABLED* - Indicates if gdb process crash debugging enabled.
56+
57+
For any environment variable indicating a feature has been enabled, it
58+
will be set when enabled and have the value 'true'.
59+
60+
For the list of server aliases, it will be a space separated list of host
61+
names.

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def find_program(names, default=None, paths=[]):
122122
WITH_HTTPD_PACKAGE = False
123123

124124
if APXS is None:
125-
APXS = find_program(['mod_wsgi-apxs'])
125+
APXS = find_program(['mod_wsgi-apxs'],
126+
paths=[os.path.dirname(sys.executable)])
126127
if APXS is not None:
127128
WITH_HTTPD_PACKAGE = True
128129

src/server/__init__.py

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,31 @@ def find_mimetypes():
781781
application-group=%%{GLOBAL}
782782
"""
783783

784+
APACHE_SERVICE_WITH_LOG_CONFIG = """
785+
<VirtualHost *:%(port)s>
786+
<IfDefine WSGI_ROTATE_LOGS>
787+
ErrorLog "|%(rotatelogs_executable)s \\
788+
%(log_directory)s/%(log_file)s.%%Y-%%m-%%d-%%H_%%M_%%S %(max_log_size)sM"
789+
</IfDefine>
790+
<IfDefine !WSGI_ROTATE_LOGS>
791+
ErrorLog "%(log_directory)s/%(log_file)s"
792+
</IfDefine>
793+
WSGIDaemonProcess 'service:%(name)s' \\
794+
display-name=%%{GROUP} \\
795+
user='%(user)s' \\
796+
group='%(group)s' \\
797+
home='%(working_directory)s' \\
798+
threads=1 \\
799+
python-path='%(python_path)s' \\
800+
python-eggs='%(python_eggs)s' \\
801+
lang='%(lang)s' \\
802+
locale='%(locale)s'
803+
WSGIImportScript '%(script)s' \\
804+
process-group='service:%(name)s' \\
805+
application-group=%%{GLOBAL}
806+
</VirtualHost>
807+
"""
808+
784809
def generate_apache_config(options):
785810
with open(options['httpd_conf'], 'w') as fp:
786811
print(APACHE_GENERAL_CONFIG % options, file=fp)
@@ -852,18 +877,35 @@ def generate_apache_config(options):
852877
file=fp)
853878

854879
if options['service_scripts']:
880+
service_log_files = {}
881+
if options['service_log_files']:
882+
service_log_files.update(options['service_log_files'])
855883
users = dict(options['service_users'] or [])
856884
groups = dict(options['service_groups'] or [])
857885
for name, script in options['service_scripts']:
858886
user = users.get(name, '${WSGI_RUN_USER}')
859887
group = groups.get(name, '${WSGI_RUN_GROUP}')
860-
print(APACHE_SERVICE_CONFIG % dict(name=name, user=user,
861-
group=group, script=script,
862-
python_path=options['python_path'],
863-
working_directory=options['working_directory'],
864-
python_eggs=options['python_eggs'],
865-
lang=options['lang'], locale=options['locale']),
866-
file=fp)
888+
if name in service_log_files:
889+
print(APACHE_SERVICE_WITH_LOG_CONFIG % dict(name=name,
890+
user=user, group=group, script=script,
891+
port=options['port'],
892+
log_directory=options['log_directory'],
893+
log_file=service_log_files[name],
894+
rotatelogs_executable=options['rotatelogs_executable'],
895+
max_log_size=options['max_log_size'],
896+
python_path=options['python_path'],
897+
working_directory=options['working_directory'],
898+
python_eggs=options['python_eggs'],
899+
lang=options['lang'], locale=options['locale']),
900+
file=fp)
901+
else:
902+
print(APACHE_SERVICE_CONFIG % dict(name=name, user=user,
903+
group=group, script=script,
904+
python_path=options['python_path'],
905+
working_directory=options['working_directory'],
906+
python_eggs=options['python_eggs'],
907+
lang=options['lang'], locale=options['locale']),
908+
file=fp)
867909

868910
if options['include_files']:
869911
for filename in options['include_files']:
@@ -1328,8 +1370,18 @@ def __call__(self, environ, start_response):
13281370
profiler_directory = '%(profiler_directory)s'
13291371
enable_recorder = %(enable_recorder)s
13301372
recorder_directory = '%(recorder_directory)s'
1373+
enable_gdb = %(enable_gdb)s
1374+
1375+
os.environ['MOD_WSGI_EXPRESS'] = 'true'
1376+
os.environ['MOD_WSGI_SERVER_NAME'] = '%(server_host)s'
1377+
os.environ['MOD_WSGI_SERVER_ALIASES'] = %(server_aliases)r or ''
1378+
1379+
if reload_on_changes:
1380+
os.environ['MOD_WSGI_RELOADER_ENABLED'] = 'true'
13311381
13321382
if debug_mode:
1383+
os.environ['MOD_WSGI_DEBUG_MODE'] = 'true'
1384+
13331385
# We need to fiddle sys.path as we are not using daemon mode and so
13341386
# the working directory will not be added to sys.path by virtue of
13351387
# 'home' option to WSGIDaemonProcess directive. We could use the
@@ -1338,11 +1390,16 @@ def __call__(self, environ, start_response):
13381390
13391391
sys.path.insert(0, working_directory)
13401392
1393+
if enable_debugger:
1394+
os.environ['MOD_WSGI_DEBUGGER_ENABLED'] = 'true'
1395+
13411396
def output_coverage_report():
13421397
coverage_info.stop()
13431398
coverage_info.html_report(directory=coverage_directory)
13441399
13451400
if enable_coverage:
1401+
os.environ['MOD_WSGI_COVERAGE_ENABLED'] = 'true'
1402+
13461403
from coverage import coverage
13471404
coverage_info = coverage()
13481405
coverage_info.start()
@@ -1355,11 +1412,19 @@ def output_profiler_data():
13551412
profiler_info.dump_stats(output_file)
13561413
13571414
if enable_profiler:
1415+
os.environ['MOD_WSGI_PROFILER_ENABLED'] = 'true'
1416+
13581417
from cProfile import Profile
13591418
profiler_info = Profile()
13601419
profiler_info.enable()
13611420
atexit.register(output_profiler_data)
13621421
1422+
if enable_recorder:
1423+
os.environ['MOD_WSGI_RECORDER_ENABLED'] = 'true'
1424+
1425+
if enable_gdb:
1426+
os.environ['MOD_WSGI_GDB_ENABLED'] = 'true'
1427+
13631428
if with_newrelic_agent:
13641429
if newrelic_config_file:
13651430
os.environ['NEW_RELIC_CONFIG_FILE'] = newrelic_config_file
@@ -2162,6 +2227,10 @@ def check_percentage(option, opt_str, value, parser):
21622227
help='When being run by the root user, the group that the '
21632228
'distinct daemon process started to run the managed service '
21642229
'should be run as.'),
2230+
optparse.make_option('--service-log-file', action='append', nargs=2,
2231+
dest='service_log_files', metavar='SERVICE FILE-NAME',
2232+
help='Specify the name of a separate log file to be used for '
2233+
'the managed service.'),
21652234

21662235
optparse.make_option('--enable-docs', action='store_true', default=False,
21672236
help='Flag indicating whether the mod_wsgi documentation should '
@@ -2668,6 +2737,8 @@ def _cmd_setup_server(command, args, options):
26682737
else:
26692738
host = options['host']
26702739

2740+
options['server_host'] = host
2741+
26712742
if options['port'] == 80:
26722743
options['url'] = 'http://%s/' % host
26732744
else:

src/server/mod_wsgi.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10081,8 +10081,8 @@ static apr_status_t wsgi_socket_send(apr_socket_t *sock, const char *buf,
1008110081
return APR_SUCCESS;
1008210082
}
1008310083

10084-
static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
10085-
int nvec)
10084+
static apr_status_t wsgi_socket_sendv_limit(apr_socket_t *sock,
10085+
struct iovec *vec, int nvec)
1008610086
{
1008710087
apr_status_t rv;
1008810088
apr_size_t written = 0;
@@ -10137,6 +10137,40 @@ static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
1013710137
return APR_SUCCESS;
1013810138
}
1013910139

10140+
static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
10141+
int nvec)
10142+
{
10143+
#if defined(_SC_IOV_MAX)
10144+
static size_t iov_max = 0;
10145+
10146+
if (iov_max == 0)
10147+
iov_max = sysconf(_SC_IOV_MAX);
10148+
#else
10149+
static size_t iov_max = APR_MAX_IOVEC_SIZE;
10150+
#endif
10151+
10152+
if (nvec > iov_max) {
10153+
int offset = 0;
10154+
10155+
while (nvec > 0) {
10156+
apr_status_t rv;
10157+
10158+
rv = wsgi_socket_sendv_limit(sock, &vec[offset],
10159+
(nvec < iov_max ? nvec : (int)iov_max));
10160+
10161+
if (rv != APR_SUCCESS)
10162+
return rv;
10163+
10164+
nvec -= iov_max;
10165+
offset += iov_max;
10166+
}
10167+
10168+
return APR_SUCCESS;
10169+
}
10170+
else
10171+
return wsgi_socket_sendv_limit(sock, vec, nvec);
10172+
}
10173+
1014010174
static apr_status_t wsgi_send_request(request_rec *r,
1014110175
WSGIRequestConfig *config,
1014210176
WSGIDaemonSocket *daemon)

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 4
28-
#define MOD_WSGI_MICROVERSION_NUMBER 10
29-
#define MOD_WSGI_VERSION_STRING "4.4.10"
28+
#define MOD_WSGI_MICROVERSION_NUMBER 11
29+
#define MOD_WSGI_VERSION_STRING "4.4.11"
3030

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

0 commit comments

Comments
 (0)