Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a program option to update oom_score_adj for child processes. #754

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions supervisor/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ def get(section, opt, *args, **kwargs):
serverurl = get(section, 'serverurl', None)
if serverurl and serverurl.strip().upper() == 'AUTO':
serverurl = None
oom_score_adj = get(section, 'oom_score_adj', None)

# find uid from "user" option
user = get(section, 'user', None)
Expand All @@ -902,7 +903,6 @@ def get(section, opt, *args, **kwargs):
umask = get(section, 'umask', None)
if umask is not None:
umask = octal_type(umask)

process_name = process_or_group_name(
get(section, 'process_name', '%(program_name)s', do_expand=False))

Expand Down Expand Up @@ -1001,6 +1001,7 @@ def get(section, opt, *args, **kwargs):
killasgroup=killasgroup,
exitcodes=exitcodes,
redirect_stderr=redirect_stderr,
oom_score_adj=oom_score_adj,
environment=environment,
serverurl=serverurl)

Expand Down Expand Up @@ -1571,6 +1572,14 @@ def close_child_pipes(self, pipes):
if fd is not None:
self.close_fd(fd)

def set_oom_score_adj(self, oom_score_adj):
try:
procfile = open('/proc/%s/oom_score_adj' % os.getpid(), 'w')
procfile.write(str(oom_score_adj) + '\n')
procfile.close()
except IOError:
return "Can't set oom_score_adj to %s" % oom_score_adj

class ClientOptions(Options):
positional_args_allowed = 1

Expand Down Expand Up @@ -1809,7 +1818,7 @@ class ProcessConfig(Config):
'stderr_logfile_backups', 'stderr_logfile_maxbytes',
'stderr_events_enabled', 'stderr_syslog',
'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup',
'exitcodes', 'redirect_stderr' ]
'exitcodes', 'redirect_stderr', 'oom_score_adj' ]
optional_param_names = [ 'environment', 'serverurl' ]

def __init__(self, options, **params):
Expand Down
12 changes: 12 additions & 0 deletions supervisor/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@ def _spawn_as_child(self, filename, argv):
self._prepare_child_fds()
# sending to fd 2 will put this output in the stderr log

# set oom_score_adj, better to do it before dropping privileges
# so it can also be decreased
oom_score_adj_msg = self.set_oom_score_adj()
if oom_score_adj_msg:
options.write(2, "supervisor: %s\n" % oom_score_adj_msg)
return

# set user
setuid_msg = self.set_uid()
if setuid_msg:
Expand Down Expand Up @@ -573,6 +580,11 @@ def set_uid(self):
msg = self.config.options.dropPrivileges(self.config.uid)
return msg

def set_oom_score_adj(self):
if self.config.oom_score_adj is None:
return
return self.config.options.set_oom_score_adj(self.config.oom_score_adj)

def __lt__(self, other):
return self.config.priority < other.config.priority

Expand Down
8 changes: 7 additions & 1 deletion supervisor/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def __init__(self):
self.changed_directory = False
self.chdir_error = None
self.umaskset = None
self.oom_score_adj_set = None
self.poller = DummyPoller(self)

def getLogger(self, *args, **kw):
Expand Down Expand Up @@ -261,6 +262,9 @@ def chdir(self, dir):
def setumask(self, mask):
self.umaskset = mask

def set_oom_score_adj(self, oom_score_adj):
self.oom_score_adj_set = oom_score_adj

class DummyLogger:
level = None

Expand Down Expand Up @@ -518,7 +522,8 @@ def __init__(self, options, name, command, directory=None, umask=None,
stderr_syslog=False,
redirect_stderr=False,
stopsignal=None, stopwaitsecs=10, stopasgroup=False, killasgroup=False,
exitcodes=(0,2), environment=None, serverurl=None):
exitcodes=(0,2), environment=None, serverurl=None,
oom_score_adj=None):
self.options = options
self.name = name
self.command = command
Expand Down Expand Up @@ -554,6 +559,7 @@ def __init__(self, options, name, command, directory=None, umask=None,
self.umask = umask
self.autochildlogs_created = False
self.serverurl = serverurl
self.oom_score_adj = oom_score_adj

def create_autochildlogs(self):
self.autochildlogs_created = True
Expand Down
6 changes: 3 additions & 3 deletions supervisor/tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -3008,7 +3008,7 @@ def _makeOne(self, *arg, **kw):
'stderr_events_enabled', 'stderr_syslog',
'stopsignal', 'stopwaitsecs', 'stopasgroup',
'killasgroup', 'exitcodes', 'redirect_stderr',
'environment'):
'environment', 'oom_score_adj'):
defaults[name] = name
for name in ('stdout_logfile_backups', 'stdout_logfile_maxbytes',
'stderr_logfile_backups', 'stderr_logfile_maxbytes'):
Expand Down Expand Up @@ -3090,7 +3090,7 @@ def _makeOne(self, *arg, **kw):
'stderr_events_enabled', 'stderr_syslog',
'stopsignal', 'stopwaitsecs', 'stopasgroup',
'killasgroup', 'exitcodes', 'redirect_stderr',
'environment'):
'environment', 'oom_score_adj'):
defaults[name] = name
for name in ('stdout_logfile_backups', 'stdout_logfile_maxbytes',
'stderr_logfile_backups', 'stderr_logfile_maxbytes'):
Expand Down Expand Up @@ -3138,7 +3138,7 @@ def _makeOne(self, *arg, **kw):
'stderr_events_enabled', 'stderr_syslog',
'stopsignal', 'stopwaitsecs', 'stopasgroup',
'killasgroup', 'exitcodes', 'redirect_stderr',
'environment'):
'environment', 'oom_score_adj'):
defaults[name] = name
for name in ('stdout_logfile_backups', 'stdout_logfile_maxbytes',
'stderr_logfile_backups', 'stderr_logfile_maxbytes'):
Expand Down
18 changes: 18 additions & 0 deletions supervisor/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,24 @@ def test_spawn_as_child_sets_umask(self):
self.assertEqual(options.written,
{2: "supervisor: child process was not spawned\n"})

def test_spawn_as_child_sets_oom_score_adj(self):
options = DummyOptions()
options.forkpid = 0
config = DummyPConfig(options, 'good', '/good/filename',
oom_score_adj=100)
instance = self._makeOne(config)
result = instance.spawn()
self.assertEqual(result, None)
self.assertEqual(options.execv_args,
('/good/filename', ['/good/filename']) )
self.assertEqual(options.oom_score_adj_set, 100)
self.assertEqual(options.execve_called, True)
# if the real execve() succeeds, the code that writes the
# "was not spawned" message won't be reached. this assertion
# is to test that no other errors were written.
self.assertEqual(options.written,
{2: "supervisor: child process was not spawned\n"})

def test_spawn_as_child_cwd_fail(self):
options = DummyOptions()
options.forkpid = 0
Expand Down
1 change: 1 addition & 0 deletions supervisor/tests/test_supervisord.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ def make_pconfig(name, command, **params):
'stopasgroup': False,
'killasgroup': False,
'exitcodes': (0,2), 'environment': None, 'serverurl': None,
'oom_score_adj': None
}
result.update(params)
return ProcessConfig(options, **result)
Expand Down