Skip to content

Commit 5956495

Browse files
Merge branch 'feature/daemon-startup-fixes' into develop
2 parents b286c1f + a607412 commit 5956495

6 files changed

Lines changed: 108 additions & 8 deletions

File tree

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.2.4.rst
89
version-4.2.3.rst
910
version-4.2.2.rst
1011
version-4.2.1.rst
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
=============
2+
Version 4.2.4
3+
=============
4+
5+
Version 4.2.4 of mod_wsgi can be obtained from:
6+
7+
https://github.com/GrahamDumpleton/mod_wsgi/archive/4.2.4.tar.gz
8+
9+
Known Issues
10+
------------
11+
12+
1. The makefiles for building mod_wsgi on Windows are currently broken and
13+
need updating. As most new changes relate to mod_wsgi daemon mode, which is
14+
not supported under Windows, you should keep using the last available
15+
binary for version 3.X on Windows instead.
16+
17+
Bugs Fixed
18+
----------
19+
20+
1. Fixed one off error in applying limit to the number of supplementary
21+
groups allowed for a daemon process group. The result could be that if
22+
more groups than the operating system allowed were specified to the option
23+
``supplementary-groups``, then memory corruption or a process crash could
24+
occur.
25+
26+
2. Improved error handling in setting up the current working directory and
27+
group access rights for a process when creating a daemon process group. The
28+
change means that if any error occurs that the daemon process group will be
29+
restarted rather than allow it to keep running with an incorrect working
30+
directory or group access rights.
31+
32+
New Features
33+
------------
34+
35+
1. Added the ``--setup-only`` option to mod_wsgi express so that it is
36+
possible to create the configuration when using the Django management command
37+
``runmodwsgi`` without actually starting the server.

src/server/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,14 @@ def check_percentage(option, opt_str, value, parser):
10601060
optparse.make_option('--enable-docs', action='store_true', default=False,
10611061
help='Flag indicating whether the mod_wsgi documentation should '
10621062
'be made available at the /__wsgi__/docs sub URL.'),
1063+
1064+
optparse.make_option('--setup-only', action='store_true', default=False,
1065+
help='Flag indicating that after the configuration files have '
1066+
'been setup, that the command should then exit and not go on '
1067+
'to actually run up the Apache server. This is to allow for '
1068+
'the generation of the configuration with Apache then later '
1069+
'being started separately using the generated \'apachectl\' '
1070+
'script.'),
10631071
)
10641072

10651073
def cmd_setup_server(params):
@@ -1350,7 +1358,7 @@ def _cmd_setup_server(command, args, options):
13501358
if options['envvars_script']:
13511359
print('Environ Variables :', options['envvars_script'])
13521360

1353-
if command == 'setup-server':
1361+
if command == 'setup-server' or options['setup_only']:
13541362
if not options['envvars_script']:
13551363
print('Environ Variables :', options['server_root'] + '/envvars')
13561364
print('Control Script :', options['server_root'] + '/apachectl')
@@ -1369,6 +1377,9 @@ def cmd_start_server(params):
13691377

13701378
config = _cmd_setup_server('start-server', args, vars(options))
13711379

1380+
if config['setup_only']:
1381+
return
1382+
13721383
executable = os.path.join(config['server_root'], 'apachectl')
13731384
name = executable.ljust(len(config['process_name']))
13741385
os.execl(executable, name, 'start', '-DNO_DETACH')

src/server/management/commands/runmodwsgi.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class Command(BaseCommand):
1010
option_list = BaseCommand.option_list + mod_wsgi.server.option_list
11-
args = '[options]'
11+
args = ''
1212
help = 'Starts Apache/mod_wsgi web server.'
1313

1414
def handle(self, *args, **options):
@@ -47,6 +47,9 @@ def handle(self, *args, **options):
4747
options = mod_wsgi.server._cmd_setup_server(
4848
'start-server', args, options)
4949

50+
if options['setup_only']:
51+
return
52+
5053
executable = os.path.join(options['server_root'], 'apachectl')
5154
name = executable.ljust(len(options['process_name']))
5255
os.execl(executable, name, 'start', '-DNO_DETACH')

src/server/mod_wsgi.c

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6690,7 +6690,7 @@ static const char *wsgi_add_daemon_process(cmd_parms *cmd, void *mconfig,
66906690
group_name = ap_getword(cmd->pool, &items, ',');
66916691

66926692
while (group_name && *group_name) {
6693-
if (groups_count > groups_maximum)
6693+
if (groups_count >= groups_maximum)
66946694
return "Too many supplementary groups WSGI daemon process";
66956695

66966696
groups[groups_count++] = ap_gname2id(group_name);
@@ -7087,7 +7087,7 @@ static void wsgi_setup_daemon_name(WSGIDaemonProcess *daemon, apr_pool_t *p)
70877087
#endif
70887088
}
70897089

7090-
static void wsgi_setup_access(WSGIDaemonProcess *daemon)
7090+
static int wsgi_setup_access(WSGIDaemonProcess *daemon)
70917091
{
70927092
/* Setup the umask for the effective user. */
70937093

@@ -7101,6 +7101,8 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71017101
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71027102
"mod_wsgi (pid=%d): Unable to change root "
71037103
"directory to '%s'.", getpid(), daemon->group->root);
7104+
7105+
return -1;
71047106
}
71057107
}
71067108

@@ -7111,6 +7113,8 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71117113
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71127114
"mod_wsgi (pid=%d): Unable to change working "
71137115
"directory to '%s'.", getpid(), daemon->group->home);
7116+
7117+
return -1;
71147118
}
71157119
}
71167120
else if (geteuid()) {
@@ -7123,12 +7127,16 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71237127
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71247128
"mod_wsgi (pid=%d): Unable to change working "
71257129
"directory to '%s'.", getpid(), pwent->pw_dir);
7130+
7131+
return -1;
71267132
}
71277133
}
71287134
else {
71297135
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71307136
"mod_wsgi (pid=%d): Unable to determine home "
71317137
"directory for uid=%ld.", getpid(), (long)geteuid());
7138+
7139+
return -1;
71327140
}
71337141
}
71347142
else {
@@ -7141,27 +7149,33 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71417149
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71427150
"mod_wsgi (pid=%d): Unable to change working "
71437151
"directory to '%s'.", getpid(), pwent->pw_dir);
7152+
7153+
return -1;
71447154
}
71457155
}
71467156
else {
71477157
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71487158
"mod_wsgi (pid=%d): Unable to determine home "
71497159
"directory for uid=%ld.", getpid(),
71507160
(long)daemon->group->uid);
7161+
7162+
return -1;
71517163
}
71527164
}
71537165

71547166
/* Don't bother switch user/group if not root. */
71557167

71567168
if (geteuid())
7157-
return;
7169+
return 0;
71587170

71597171
/* Setup the daemon process real and effective group. */
71607172

71617173
if (setgid(daemon->group->gid) == -1) {
71627174
ap_log_error(APLOG_MARK, APLOG_ALERT, errno, wsgi_server,
71637175
"mod_wsgi (pid=%d): Unable to set group id to gid=%u.",
71647176
getpid(), (unsigned)daemon->group->gid);
7177+
7178+
return -1;
71657179
}
71667180
else {
71677181
if (daemon->group->groups) {
@@ -7172,13 +7186,17 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71727186
"to set supplementary groups for uname=%s "
71737187
"of '%s'.", getpid(), daemon->group->user,
71747188
daemon->group->groups_list);
7189+
7190+
return -1;
71757191
}
71767192
}
71777193
else if (initgroups(daemon->group->user, daemon->group->gid) == -1) {
71787194
ap_log_error(APLOG_MARK, APLOG_ALERT, errno,
71797195
wsgi_server, "mod_wsgi (pid=%d): Unable "
71807196
"to set groups for uname=%s and gid=%u.", getpid(),
71817197
daemon->group->user, (unsigned)daemon->group->gid);
7198+
7199+
return -1;
71827200
}
71837201
}
71847202

@@ -7196,8 +7214,19 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
71967214
* reached their process limit. In that case will be left
71977215
* running as wrong user. Just exit on all failures to be
71987216
* safe. Don't die immediately to avoid a fork bomb.
7217+
*
7218+
* We could just return -1 here and let the caller do the
7219+
* sleep() and exit() but this failure is critical enough
7220+
* that we still do it here so it is obvious that the issue
7221+
* is being addressed.
71997222
*/
72007223

7224+
ap_log_error(APLOG_MARK, APLOG_ALERT, 0, wsgi_server,
7225+
"mod_wsgi (pid=%d): Failure to configure the "
7226+
"daemon process correctly and process left in "
7227+
"unspecified state. Restarting daemon process "
7228+
"after delay.", getpid());
7229+
72017230
sleep(20);
72027231

72037232
exit(-1);
@@ -7219,6 +7248,8 @@ static void wsgi_setup_access(WSGIDaemonProcess *daemon)
72197248
}
72207249
}
72217250
#endif
7251+
7252+
return 0;
72227253
}
72237254

72247255
static int wsgi_setup_socket(WSGIProcessGroup *process)
@@ -8561,7 +8592,24 @@ static int wsgi_start_process(apr_pool_t *p, WSGIDaemonProcess *daemon)
85618592

85628593
/* Setup daemon process user/group/umask etc. */
85638594

8564-
wsgi_setup_access(daemon);
8595+
if (wsgi_setup_access(daemon) == -1) {
8596+
/*
8597+
* If we get any failure from setting up the appropriate
8598+
* permissions or working directory for the daemon process
8599+
* then we exit the process. Don't die immediately to avoid
8600+
* a fork bomb.
8601+
*/
8602+
8603+
ap_log_error(APLOG_MARK, APLOG_ALERT, 0, wsgi_server,
8604+
"mod_wsgi (pid=%d): Failure to configure the "
8605+
"daemon process correctly and process left in "
8606+
"unspecified state. Restarting daemon process "
8607+
"after delay.", getpid());
8608+
8609+
sleep(20);
8610+
8611+
exit(-1);
8612+
}
85658613

85668614
/* Reinitialise accept mutex in daemon process. */
85678615

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 2
28-
#define MOD_WSGI_MICROVERSION_NUMBER 3
29-
#define MOD_WSGI_VERSION_STRING "4.2.3"
28+
#define MOD_WSGI_MICROVERSION_NUMBER 4
29+
#define MOD_WSGI_VERSION_STRING "4.2.4"
3030

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

0 commit comments

Comments
 (0)