Skip to content

Commit 7c179a3

Browse files
Fix daemon error log for IP based virtual host with wildcard Listen.
When using daemon mode with a VirtualHost selected by IP address while the Listen directive used a wildcard, output to wsgi.errors, sys.stdout and sys.stderr was written to the main server ErrorLog instead of the ErrorLog of that VirtualHost. To match the request back to a server the daemon reconstructed the local socket address from the listener socket bind address, but for a wildcard listener that address is 0.0.0.0 (or ::) and never matched a VirtualHost given a specific IP address, so the match fell back to the main server. Reconstruct the local address from the actual local IP the connection was received on, carried across as SERVER_ADDR, which is what the Apache child worker uses for the same matching. This is the original problem reported in issue #307.
1 parent ba085e9 commit 7c179a3

2 files changed

Lines changed: 65 additions & 13 deletions

File tree

docs/release-notes/version-6.0.1.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,15 @@ Bugs Fixed
4949
``MOD_WSGI_WITH_DAEMONS`` into a daemon specific header that the affected
5050
source file did not include. The definition has been moved to a common
5151
header visible to all source files.
52+
53+
* When using daemon mode with a ``VirtualHost`` selected by IP address while
54+
the ``Listen`` directive used a wildcard, output written to ``wsgi.errors``
55+
(and ``sys.stdout`` or ``sys.stderr``) was written to the main server
56+
``ErrorLog`` instead of the ``ErrorLog`` of that ``VirtualHost``. To match
57+
the request to a server the daemon process reconstructed the local socket
58+
address from the listener socket bind address, but for a wildcard listener
59+
that address is ``0.0.0.0`` (or ``::``) and so never matched a
60+
``VirtualHost`` given by a specific IP address, causing the match to fall
61+
back to the main server. The daemon now reconstructs the local address from
62+
the actual local IP the connection was received on, which is what the
63+
Apache child worker uses for the same matching.

src/server/wsgi_daemon.c

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,22 +4642,62 @@ int wsgi_hook_daemon_handler(conn_rec *c)
46424642
r->useragent_addr = c->client_addr;
46434643
r->useragent_ip = c->client_ip;
46444644

4645-
key = apr_psprintf(p, "%s|%s",
4646-
apr_table_get(r->subprocess_env,
4647-
"mod_wsgi.listener_host"),
4648-
apr_table_get(r->subprocess_env,
4649-
"mod_wsgi.listener_port"));
4645+
/*
4646+
* Reconstruct the local socket address the original connection was
4647+
* accepted on in the Apache child worker, so that the virtual host
4648+
* matching below resolves to the same server, and therefore the
4649+
* same error log, as the Apache child worker resolved to. The
4650+
* genuine local IP the client connected to is carried across as
4651+
* SERVER_ADDR. It must be used in preference to the listener socket
4652+
* bind address, because when the Listen directive uses a wildcard
4653+
* the bind address is 0.0.0.0 (or ::) and would never match a
4654+
* VirtualHost specified by IP address.
4655+
*/
46504656

4651-
wsgi_log_error(APLOG_TRACE1, 0, wsgi_server,
4652-
"Server listener address '%s'.", key);
4657+
addr = NULL;
46534658

4654-
addr = (apr_sockaddr_t *)apr_hash_get(wsgi_daemon_listeners,
4655-
key, APR_HASH_KEY_STRING);
4659+
{
4660+
const char *local_ip;
4661+
const char *local_port;
46564662

4657-
wsgi_log_error(APLOG_TRACE1, 0, wsgi_server,
4658-
"Server listener address '%s' was%s found in lookup "
4659-
"table.",
4660-
key, addr ? "" : " not");
4663+
local_ip = apr_table_get(r->subprocess_env, "SERVER_ADDR");
4664+
local_port = apr_table_get(r->subprocess_env,
4665+
"mod_wsgi.listener_port");
4666+
4667+
if (local_ip && *local_ip)
4668+
{
4669+
if (apr_sockaddr_info_get(&addr, local_ip, APR_UNSPEC,
4670+
local_port ? atoi(local_port) : 0,
4671+
0, p) != APR_SUCCESS)
4672+
addr = NULL;
4673+
}
4674+
4675+
wsgi_log_error(APLOG_TRACE1, 0, wsgi_server,
4676+
"Server local address reconstructed as '%s|%s'.",
4677+
local_ip ? local_ip : "",
4678+
local_port ? local_port : "");
4679+
4680+
/*
4681+
* Fall back to the table of listener socket bind addresses,
4682+
* keyed on listener host and port, if the address could not be
4683+
* reconstructed from SERVER_ADDR.
4684+
*/
4685+
4686+
if (!addr)
4687+
{
4688+
key = apr_psprintf(p, "%s|%s",
4689+
apr_table_get(r->subprocess_env,
4690+
"mod_wsgi.listener_host"),
4691+
local_port ? local_port : "");
4692+
4693+
addr = (apr_sockaddr_t *)apr_hash_get(wsgi_daemon_listeners,
4694+
key, APR_HASH_KEY_STRING);
4695+
4696+
wsgi_log_error(APLOG_TRACE1, 0, wsgi_server,
4697+
"Server listener address '%s' was%s found in "
4698+
"lookup table.", key, addr ? "" : " not");
4699+
}
4700+
}
46614701

46624702
if (addr)
46634703
{

0 commit comments

Comments
 (0)