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

Added a "restartpause" option + fixing travis-checks #659

Open
wants to merge 4 commits 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
12 changes: 12 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,18 @@ where specified.

*Introduced*: 3.0

``restartpause``

Adds a pause (in seconds) between successive failed start attempts - thus
throttles failed-start attempts and prevents massive load increase during
this.

*Default*: 0

*Required*: No.

*Introduced*: 4.0 (?)

``autorestart``

Specifies if :program:`supervisord` should automatically restart a
Expand Down
4 changes: 3 additions & 1 deletion supervisor/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,7 @@ def get(section, opt, *args, **kwargs):
autorestart = auto_restart(get(section, 'autorestart', 'unexpected'))
startsecs = integer(get(section, 'startsecs', 1))
startretries = integer(get(section, 'startretries', 3))
restartpause = integer(get(section, 'restartpause', 0))
stopsignal = signal_number(get(section, 'stopsignal', 'TERM'))
stopwaitsecs = integer(get(section, 'stopwaitsecs', 10))
stopasgroup = boolean(get(section, 'stopasgroup', 'false'))
Expand Down Expand Up @@ -978,6 +979,7 @@ def get(section, opt, *args, **kwargs):
autorestart=autorestart,
startsecs=startsecs,
startretries=startretries,
restartpause=restartpause,
uid=uid,
stdout_logfile=logfiles['stdout_logfile'],
stdout_capture_maxbytes = stdout_cmaxbytes,
Expand Down Expand Up @@ -1789,7 +1791,7 @@ def __repr__(self):
class ProcessConfig(Config):
req_param_names = [
'name', 'uid', 'command', 'directory', 'umask', 'priority',
'autostart', 'autorestart', 'startsecs', 'startretries',
'autostart', 'autorestart', 'startsecs', 'startretries', 'restartpause',
'stdout_logfile', 'stdout_capture_maxbytes',
'stdout_events_enabled', 'stdout_syslog',
'stdout_logfile_backups', 'stdout_logfile_maxbytes',
Expand Down
7 changes: 5 additions & 2 deletions supervisor/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def change_state(self, new_state, expected=True):
if new_state == ProcessStates.BACKOFF:
now = time.time()
self.backoff += 1
self.delay = now + self.backoff
self.delay = now + self.backoff + self.config.restartpause

self.state = new_state

Expand Down Expand Up @@ -544,6 +544,9 @@ def finish(self, pid, sts):
# unexpected exit code
self.spawnerr = 'Bad exit code %s' % es
msg = "exited: %s (%s)" % (processname, msg + "; not expected")
self.delay = now + self.config.restartpause
if self.config.restartpause > 0:
msg += ". Will restart in %s seconds (restartpause)" % self.config.restartpause
self.change_state(ProcessStates.EXITED, expected=False)

self.config.options.logger.info(msg)
Expand Down Expand Up @@ -593,7 +596,7 @@ def transition(self):
if self.config.options.mood > SupervisorStates.RESTARTING:
# dont start any processes if supervisor is shutting down
if state == ProcessStates.EXITED:
if self.config.autorestart:
if self.config.autorestart and now > self.delay:
if self.config.autorestart is RestartUnconditionally:
# EXITED -> STARTING
self.spawn()
Expand Down
1 change: 1 addition & 0 deletions supervisor/skel/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
;autostart=true ; start at supervisord start (default: true)
;startsecs=1 ; # of secs prog must stay up to be running (def. 1)
;startretries=3 ; max # of serial start failures when starting (default 3)
;restartpause=0 ; number of seconds to wait after a failed start attempt
;autorestart=unexpected ; when to restart if exited after running (def: unexpected)
;exitcodes=0,2 ; 'expected' exit codes used with autorestart (default 0,2)
;stopsignal=QUIT ; signal used to kill process (default TERM)
Expand Down
3 changes: 2 additions & 1 deletion supervisor/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ def __lt__(self, other):
class DummyPConfig:
def __init__(self, options, name, command, directory=None, umask=None,
priority=999, autostart=True,
autorestart=True, startsecs=10, startretries=999,
autorestart=True, startsecs=10, startretries=999, restartpause=2,
uid=None, stdout_logfile=None, stdout_capture_maxbytes=0,
stdout_events_enabled=False,
stdout_logfile_backups=0, stdout_logfile_maxbytes=0,
Expand All @@ -527,6 +527,7 @@ def __init__(self, options, name, command, directory=None, umask=None,
self.autorestart = autorestart
self.startsecs = startsecs
self.startretries = startretries
self.restartpause = restartpause
self.uid = uid
self.stdout_logfile = stdout_logfile
self.stdout_capture_maxbytes = stdout_capture_maxbytes
Expand Down
13 changes: 10 additions & 3 deletions supervisor/tests/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def test_options(self):
stopwaitsecs=5
startsecs=5
startretries=10
restartpause=2
directory=/tmp
umask=002

Expand Down Expand Up @@ -539,6 +540,7 @@ def test_options(self):
self.assertEqual(proc1.autorestart, datatypes.RestartWhenExitUnexpected)
self.assertEqual(proc1.startsecs, 5)
self.assertEqual(proc1.startretries, 10)
self.assertEqual(proc1.restartpause, 2)
self.assertEqual(proc1.uid, 0)
self.assertEqual(proc1.stdout_logfile, '/tmp/cat.log')
self.assertEqual(proc1.stopsignal, signal.SIGKILL)
Expand Down Expand Up @@ -1428,6 +1430,7 @@ def test_processes_from_section(self):
autorestart = false
startsecs = 100
startretries = 100
restartpause = 2
user = root
stdout_logfile = NONE
stdout_logfile_backups = 1
Expand All @@ -1454,6 +1457,7 @@ def test_processes_from_section(self):
self.assertEqual(pconfig.autorestart, False)
self.assertEqual(pconfig.startsecs, 100)
self.assertEqual(pconfig.startretries, 100)
self.assertEqual(pconfig.restartpause, 2)
self.assertEqual(pconfig.uid, 0)
self.assertEqual(pconfig.stdout_logfile, None)
self.assertEqual(pconfig.stdout_capture_maxbytes, 0)
Expand Down Expand Up @@ -1615,6 +1619,7 @@ def test_options_with_environment_expansions(self):
stopwaitsecs=%(ENV_CAT1_STOPWAIT)s
startsecs=%(ENV_CAT1_STARTWAIT)s
startretries=%(ENV_CAT1_STARTRETRIES)s
restartpause=%(ENV_CAT1_RESTARTPAUSE)s
directory=%(ENV_CAT1_DIR)s
umask=%(ENV_CAT1_UMASK)s
""")
Expand Down Expand Up @@ -1648,6 +1653,7 @@ def test_options_with_environment_expansions(self):
'ENV_CAT1_STOPWAIT': '5',
'ENV_CAT1_STARTWAIT': '5',
'ENV_CAT1_STARTRETRIES': '10',
'ENV_CAT1_RESTARTPAUSE': '2',
'ENV_CAT1_DIR': '/tmp',
'ENV_CAT1_UMASK': '002',
}
Expand Down Expand Up @@ -1692,6 +1698,7 @@ def test_options_with_environment_expansions(self):
self.assertEqual(proc1.autorestart, datatypes.RestartWhenExitUnexpected)
self.assertEqual(proc1.startsecs, 5)
self.assertEqual(proc1.startretries, 10)
self.assertEqual(proc1.restartpause, 2)
self.assertEqual(proc1.uid, 0)
self.assertEqual(proc1.stdout_logfile, '/tmp/cat.log')
self.assertEqual(proc1.stopsignal, signal.SIGKILL)
Expand Down Expand Up @@ -2920,7 +2927,7 @@ def _makeOne(self, *arg, **kw):
defaults = {}
for name in ('name', 'command', 'directory', 'umask',
'priority', 'autostart', 'autorestart',
'startsecs', 'startretries', 'uid',
'startsecs', 'startretries', 'restartpause' ,'uid',
'stdout_logfile', 'stdout_capture_maxbytes',
'stdout_events_enabled', 'stdout_syslog',
'stderr_logfile', 'stderr_capture_maxbytes',
Expand Down Expand Up @@ -3002,7 +3009,7 @@ def _makeOne(self, *arg, **kw):
defaults = {}
for name in ('name', 'command', 'directory', 'umask',
'priority', 'autostart', 'autorestart',
'startsecs', 'startretries', 'uid',
'startsecs', 'startretries', 'restartpause' ,'uid',
'stdout_logfile', 'stdout_capture_maxbytes',
'stdout_events_enabled', 'stdout_syslog',
'stderr_logfile', 'stderr_capture_maxbytes',
Expand Down Expand Up @@ -3050,7 +3057,7 @@ def _makeOne(self, *arg, **kw):
defaults = {}
for name in ('name', 'command', 'directory', 'umask',
'priority', 'autostart', 'autorestart',
'startsecs', 'startretries', 'uid',
'startsecs', 'startretries', 'restartpause', 'uid',
'stdout_logfile', 'stdout_capture_maxbytes',
'stdout_events_enabled', 'stdout_syslog',
'stderr_logfile', 'stderr_capture_maxbytes',
Expand Down
2 changes: 1 addition & 1 deletion supervisor/tests/test_supervisord.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def make_pconfig(name, command, **params):
result = {
'name': name, 'command': command,
'directory': None, 'umask': None, 'priority': 999, 'autostart': True,
'autorestart': True, 'startsecs': 10, 'startretries': 999,
'autorestart': True, 'startsecs': 10, 'startretries': 999, 'restartpause': 2,
'uid': None, 'stdout_logfile': None, 'stdout_capture_maxbytes': 0,
'stdout_events_enabled': False,
'stdout_logfile_backups': 0, 'stdout_logfile_maxbytes': 0,
Expand Down