Skip to content

Commit a95213f

Browse files
committed
Tweaks to the initial environment_{file|loader} implementation
- Remove the blocking call to subprocess.check_output in the main supervisord process. Instead make that call in the child process immediately after the initial fork, before doing any changes to the process config and state. This keeps the blocking call out of the danger zone, while still keeping the simple design.
1 parent 8f1675a commit a95213f

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

Diff for: supervisor/options.py

+8-13
Original file line numberDiff line numberDiff line change
@@ -1955,7 +1955,8 @@ def make_dispatchers(self, proc):
19551955
def load_external_environment_definition(self):
19561956
return self.load_external_environment_definition_for_config(self)
19571957

1958-
# this is separated out in order to make it easier to test
1958+
# NOTE - THIS IS BLOCKING CODE AND MUST ONLY BE CALLED IN TESTS OR IN CHILD PROCESSES, NOT THE
1959+
# MAIN SUPERVISORD THREAD OF EXECUTION
19591960
@classmethod
19601961
def load_external_environment_definition_for_config(cls, config):
19611962
# lazily load extra env vars before we drop privileges so that this can be used to load a secrets file
@@ -1976,21 +1977,15 @@ def load_external_environment_definition_for_config(cls, config):
19761977

19771978
elif config.environment_loader:
19781979
try:
1979-
from subprocess import check_output, CalledProcessError
1980-
kwargs = dict(shell=True)
1981-
if sys.version_info.major >= 3:
1982-
if sys.version_info.minor >= 7:
1983-
kwargs['text'] = True
1984-
else:
1985-
pass # we will decode the bytes returned after reading it for these versions of python
1986-
1987-
envdata = check_output(config.environment_loader, **kwargs)
1980+
from subprocess import check_output, CalledProcessError, STDOUT as subprocess_STDOUT
19881981

1989-
if sys.version_info.major >= 3 and sys.version_info.minor < 7:
1990-
envdata = envdata.decode('utf8')
1982+
envdata = check_output(config.environment_loader, shell=True, stderr=subprocess_STDOUT)
1983+
envdata = as_string(envdata)
19911984

19921985
except CalledProcessError as e:
1993-
raise ProcessException("environment_loader failure with %s: %d, %s" % (config.environment_loader, e.returncode, e.output))
1986+
raise ProcessException("environment_loader failure with %s: %d, %s" % \
1987+
(config.environment_loader, e.returncode, as_string(e.output))
1988+
)
19941989

19951990
if envdata:
19961991
extra_env = {}

Diff for: supervisor/process.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ def spawn(self):
218218
try:
219219
filename, argv = self.get_execv_args()
220220

221-
# check the environment_file/environment_loader options before we fork to simplify child process management
222-
extra_env = self.config.load_external_environment_definition()
223-
224221
except ProcessException as what:
225222
self.record_spawnerr(what.args[0])
226223
self._assertInState(ProcessStates.STARTING)
@@ -264,7 +261,7 @@ def spawn(self):
264261
return self._spawn_as_parent(pid)
265262

266263
else:
267-
return self._spawn_as_child(filename, argv, extra_env=extra_env)
264+
return self._spawn_as_child(filename, argv)
268265

269266
def _spawn_as_parent(self, pid):
270267
# Parent
@@ -288,9 +285,17 @@ def _prepare_child_fds(self):
288285
for i in range(3, options.minfds):
289286
options.close_fd(i)
290287

291-
def _spawn_as_child(self, filename, argv, extra_env=None):
288+
def _spawn_as_child(self, filename, argv):
292289
options = self.config.options
293290
try:
291+
# check the environment_file/environment_loader options after forking in order to avoid blocking the
292+
# main supervisord thread, but do it before we start to mix up the process signals/state
293+
try:
294+
extra_env = self.config.load_external_environment_definition()
295+
except ProcessException as e:
296+
self.record_spawnerr(e.args[0])
297+
raise
298+
294299
# prevent child from receiving signals sent to the
295300
# parent by calling os.setpgrp to create a new process
296301
# group for the child; this prevents, for instance,

0 commit comments

Comments
 (0)