summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst12
-rw-r--r--docs/release-notes/index.rst1
-rw-r--r--docs/release-notes/version-4.4.11.rst61
-rw-r--r--setup.py3
-rw-r--r--src/server/__init__.py85
-rw-r--r--src/server/mod_wsgi.c38
-rw-r--r--src/server/wsgi_version.h4
7 files changed, 180 insertions, 24 deletions
diff --git a/README.rst b/README.rst
index 269d04c..6de83f6 100644
--- a/README.rst
+++ b/README.rst
@@ -296,15 +296,3 @@ agent configuration file.
export NEW_RELIC_CONFIG_FILE
mod_wsgi-express start-server wsgi.py --with-newrelic
-
-When using this option, if you have also installed the ``mod_wsgi-metrics``
-Python package, then additional metrics about Apache and mod_wsgi will also
-be reported via the New Relic Platform API. These will appear as a separate
-set of dashboards under 'mod_wsgi' in the left hand side navigation bar of
-the New Relic UI.
-
-New Relic provides a free Lite tier so there is no excuse for not using it.
-Learn about what your Python web application is really doing. [1]_
-
-.. [1] Disclaimer: I work for New Relic and am the primary developer of
- the Python agent. So of course it is awesome. :-)
diff --git a/docs/release-notes/index.rst b/docs/release-notes/index.rst
index 70ec171..f57fa2a 100644
--- a/docs/release-notes/index.rst
+++ b/docs/release-notes/index.rst
@@ -5,6 +5,7 @@ Release Notes
.. toctree::
:maxdepth: 2
+ version-4.4.11.rst
version-4.4.10.rst
version-4.4.9.rst
version-4.4.8.rst
diff --git a/docs/release-notes/version-4.4.11.rst b/docs/release-notes/version-4.4.11.rst
new file mode 100644
index 0000000..1001a1d
--- /dev/null
+++ b/docs/release-notes/version-4.4.11.rst
@@ -0,0 +1,61 @@
+==============
+Version 4.4.11
+==============
+
+Version 4.4.11 of mod_wsgi can be obtained from:
+
+ https://codeload.github.com/GrahamDumpleton/mod_wsgi/tar.gz/4.4.11
+
+For details on the availability of Windows binaries see:
+
+ https://github.com/GrahamDumpleton/mod_wsgi/tree/master/win32
+
+Bugs Fixed
+----------
+
+1. No provision was made for operating systems with a very low limit on the
+number of separate data blocks that could be passed to system ``writev()``
+call. This was an issue on Solaris where the limit is 16 and meant that since
+version 4.4.0, daemon mode of mod_wsgi would fail where a HTTP request had
+more than a small number of headers.
+
+2. When installing the ``mod_wsgi`` package using ``pip`` and rather
+than activating the virtual environment you were referring to ``pip`` by
+path from the ``bin`` directory, the ``mod_wsgi-httpd`` package which
+had already been installed into the virtual environment would not be
+detected.
+
+New Features
+------------
+
+1. Added the ``--service-log`` option to ``mod_wsgi-express`` for
+specifying the name of a log file for a specific service script. The
+arguments are the name of the service and the file name for the log. The
+log file will be placed in the log directory, be it the default, or a
+specific log directory if specified.
+
+2. Set various environment variables from ``mod_wsgi-express`` to identify
+that it is being used, what hosts it is handling requests for, and whether
+debug mode and/or specific debug mode features are enabled. This is so that
+a web application can modify it's behaviour when ``mod_wsgi-express`` is
+being used, or being used in specific ways. The environment variables which
+are set are:
+
+* *MOD_WSGI_EXPRESS* - Indicates that ``mod_wsgi-express`` is being used.
+* *MOD_WSGI_SERVER_NAME* - The primary server host name for the site.
+* *MOD_WSGI_SERVER_ALIASES* - Secondary host names the site is known by.
+* *MOD_WSGI_RELOADER_ENABLED* - Indicates if source code reloading enabled.
+* *MOD_WSGI_DEBUG_MODE* - Indicates if debug mode has been enabled.
+* *MOD_WSGI_DEBUGGER_ENABLED* - Indicates pdb debugger has been enabled.
+* *MOD_WSGI_COVERAGE_ENABLED* - Indicates if coverage analysis has been
+ enabled.
+* *MOD_WSGI_PROFILER_ENABLED* - Indicates if code profiling has been enabled.
+* *MOD_WSGI_RECORDER_ENABLED* - Indicates if request/response recording
+ enabled.
+* *MOD_WSGI_GDB_ENABLED* - Indicates if gdb process crash debugging enabled.
+
+For any environment variable indicating a feature has been enabled, it
+will be set when enabled and have the value 'true'.
+
+For the list of server aliases, it will be a space separated list of host
+names.
diff --git a/setup.py b/setup.py
index 8329497..1275fbc 100644
--- a/setup.py
+++ b/setup.py
@@ -122,7 +122,8 @@ APXS = os.environ.get('APXS')
WITH_HTTPD_PACKAGE = False
if APXS is None:
- APXS = find_program(['mod_wsgi-apxs'])
+ APXS = find_program(['mod_wsgi-apxs'],
+ paths=[os.path.dirname(sys.executable)])
if APXS is not None:
WITH_HTTPD_PACKAGE = True
diff --git a/src/server/__init__.py b/src/server/__init__.py
index fa26232..2bf5d4f 100644
--- a/src/server/__init__.py
+++ b/src/server/__init__.py
@@ -781,6 +781,31 @@ WSGIImportScript '%(script)s' \\
application-group=%%{GLOBAL}
"""
+APACHE_SERVICE_WITH_LOG_CONFIG = """
+<VirtualHost *:%(port)s>
+<IfDefine WSGI_ROTATE_LOGS>
+ErrorLog "|%(rotatelogs_executable)s \\
+ %(log_directory)s/%(log_file)s.%%Y-%%m-%%d-%%H_%%M_%%S %(max_log_size)sM"
+</IfDefine>
+<IfDefine !WSGI_ROTATE_LOGS>
+ErrorLog "%(log_directory)s/%(log_file)s"
+</IfDefine>
+WSGIDaemonProcess 'service:%(name)s' \\
+ display-name=%%{GROUP} \\
+ user='%(user)s' \\
+ group='%(group)s' \\
+ home='%(working_directory)s' \\
+ threads=1 \\
+ python-path='%(python_path)s' \\
+ python-eggs='%(python_eggs)s' \\
+ lang='%(lang)s' \\
+ locale='%(locale)s'
+WSGIImportScript '%(script)s' \\
+ process-group='service:%(name)s' \\
+ application-group=%%{GLOBAL}
+</VirtualHost>
+"""
+
def generate_apache_config(options):
with open(options['httpd_conf'], 'w') as fp:
print(APACHE_GENERAL_CONFIG % options, file=fp)
@@ -852,18 +877,35 @@ def generate_apache_config(options):
file=fp)
if options['service_scripts']:
+ service_log_files = {}
+ if options['service_log_files']:
+ service_log_files.update(options['service_log_files'])
users = dict(options['service_users'] or [])
groups = dict(options['service_groups'] or [])
for name, script in options['service_scripts']:
user = users.get(name, '${WSGI_RUN_USER}')
group = groups.get(name, '${WSGI_RUN_GROUP}')
- print(APACHE_SERVICE_CONFIG % dict(name=name, user=user,
- group=group, script=script,
- python_path=options['python_path'],
- working_directory=options['working_directory'],
- python_eggs=options['python_eggs'],
- lang=options['lang'], locale=options['locale']),
- file=fp)
+ if name in service_log_files:
+ print(APACHE_SERVICE_WITH_LOG_CONFIG % dict(name=name,
+ user=user, group=group, script=script,
+ port=options['port'],
+ log_directory=options['log_directory'],
+ log_file=service_log_files[name],
+ rotatelogs_executable=options['rotatelogs_executable'],
+ max_log_size=options['max_log_size'],
+ python_path=options['python_path'],
+ working_directory=options['working_directory'],
+ python_eggs=options['python_eggs'],
+ lang=options['lang'], locale=options['locale']),
+ file=fp)
+ else:
+ print(APACHE_SERVICE_CONFIG % dict(name=name, user=user,
+ group=group, script=script,
+ python_path=options['python_path'],
+ working_directory=options['working_directory'],
+ python_eggs=options['python_eggs'],
+ lang=options['lang'], locale=options['locale']),
+ file=fp)
if options['include_files']:
for filename in options['include_files']:
@@ -1328,8 +1370,18 @@ enable_profiler = %(enable_profiler)s
profiler_directory = '%(profiler_directory)s'
enable_recorder = %(enable_recorder)s
recorder_directory = '%(recorder_directory)s'
+enable_gdb = %(enable_gdb)s
+
+os.environ['MOD_WSGI_EXPRESS'] = 'true'
+os.environ['MOD_WSGI_SERVER_NAME'] = '%(server_host)s'
+os.environ['MOD_WSGI_SERVER_ALIASES'] = %(server_aliases)r or ''
+
+if reload_on_changes:
+ os.environ['MOD_WSGI_RELOADER_ENABLED'] = 'true'
if debug_mode:
+ os.environ['MOD_WSGI_DEBUG_MODE'] = 'true'
+
# We need to fiddle sys.path as we are not using daemon mode and so
# the working directory will not be added to sys.path by virtue of
# 'home' option to WSGIDaemonProcess directive. We could use the
@@ -1338,11 +1390,16 @@ if debug_mode:
sys.path.insert(0, working_directory)
+if enable_debugger:
+ os.environ['MOD_WSGI_DEBUGGER_ENABLED'] = 'true'
+
def output_coverage_report():
coverage_info.stop()
coverage_info.html_report(directory=coverage_directory)
if enable_coverage:
+ os.environ['MOD_WSGI_COVERAGE_ENABLED'] = 'true'
+
from coverage import coverage
coverage_info = coverage()
coverage_info.start()
@@ -1355,11 +1412,19 @@ def output_profiler_data():
profiler_info.dump_stats(output_file)
if enable_profiler:
+ os.environ['MOD_WSGI_PROFILER_ENABLED'] = 'true'
+
from cProfile import Profile
profiler_info = Profile()
profiler_info.enable()
atexit.register(output_profiler_data)
+if enable_recorder:
+ os.environ['MOD_WSGI_RECORDER_ENABLED'] = 'true'
+
+if enable_gdb:
+ os.environ['MOD_WSGI_GDB_ENABLED'] = 'true'
+
if with_newrelic_agent:
if newrelic_config_file:
os.environ['NEW_RELIC_CONFIG_FILE'] = newrelic_config_file
@@ -2162,6 +2227,10 @@ option_list = (
help='When being run by the root user, the group that the '
'distinct daemon process started to run the managed service '
'should be run as.'),
+ optparse.make_option('--service-log-file', action='append', nargs=2,
+ dest='service_log_files', metavar='SERVICE FILE-NAME',
+ help='Specify the name of a separate log file to be used for '
+ 'the managed service.'),
optparse.make_option('--enable-docs', action='store_true', default=False,
help='Flag indicating whether the mod_wsgi documentation should '
@@ -2668,6 +2737,8 @@ def _cmd_setup_server(command, args, options):
else:
host = options['host']
+ options['server_host'] = host
+
if options['port'] == 80:
options['url'] = 'http://%s/' % host
else:
diff --git a/src/server/mod_wsgi.c b/src/server/mod_wsgi.c
index b900303..09dc527 100644
--- a/src/server/mod_wsgi.c
+++ b/src/server/mod_wsgi.c
@@ -10081,8 +10081,8 @@ static apr_status_t wsgi_socket_send(apr_socket_t *sock, const char *buf,
return APR_SUCCESS;
}
-static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
- int nvec)
+static apr_status_t wsgi_socket_sendv_limit(apr_socket_t *sock,
+ struct iovec *vec, int nvec)
{
apr_status_t rv;
apr_size_t written = 0;
@@ -10137,6 +10137,40 @@ static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
return APR_SUCCESS;
}
+static apr_status_t wsgi_socket_sendv(apr_socket_t *sock, struct iovec *vec,
+ int nvec)
+{
+#if defined(_SC_IOV_MAX)
+ static size_t iov_max = 0;
+
+ if (iov_max == 0)
+ iov_max = sysconf(_SC_IOV_MAX);
+#else
+ static size_t iov_max = APR_MAX_IOVEC_SIZE;
+#endif
+
+ if (nvec > iov_max) {
+ int offset = 0;
+
+ while (nvec > 0) {
+ apr_status_t rv;
+
+ rv = wsgi_socket_sendv_limit(sock, &vec[offset],
+ (nvec < iov_max ? nvec : (int)iov_max));
+
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ nvec -= iov_max;
+ offset += iov_max;
+ }
+
+ return APR_SUCCESS;
+ }
+ else
+ return wsgi_socket_sendv_limit(sock, vec, nvec);
+}
+
static apr_status_t wsgi_send_request(request_rec *r,
WSGIRequestConfig *config,
WSGIDaemonSocket *daemon)
diff --git a/src/server/wsgi_version.h b/src/server/wsgi_version.h
index ed32b06..ea29f10 100644
--- a/src/server/wsgi_version.h
+++ b/src/server/wsgi_version.h
@@ -25,8 +25,8 @@
#define MOD_WSGI_MAJORVERSION_NUMBER 4
#define MOD_WSGI_MINORVERSION_NUMBER 4
-#define MOD_WSGI_MICROVERSION_NUMBER 10
-#define MOD_WSGI_VERSION_STRING "4.4.10"
+#define MOD_WSGI_MICROVERSION_NUMBER 11
+#define MOD_WSGI_VERSION_STRING "4.4.11"
/* ------------------------------------------------------------------------- */