19 Commits

Author SHA1 Message Date
Tanmoy Sarkar
642387dd0e fix(companion): Apply dead config settings and validate specs
Three companion settings were documented and configurable but never had any
effect. companion_restart_delay was ignored because CompanionProcess hardcoded
a 5s delay; it is now read from config and kept out of config_hash, since it
does not affect the spawned process and so must not trigger a restart on
reread. companion_config_file was never read; the manager now loads its
companion settings from that dedicated file when set, instead of always reading
the main gunicorn config. companion_manager_stop_timeout was unused, so
shutdown waited only graceful_timeout before SIGKILLing the manager and cut
short long-draining companions; stop now waits the larger of graceful_timeout
and the manager stop timeout, derived from the slowest companion stop_timeout
plus the buffer when not set explicitly.

Worker specs now reject unknown keys so a typo fails loudly instead of silently
falling back to a default. Also correct the spawn_companion_manager docstring,
drop its unused return value, and fix the README config-file description.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 22:51:19 +05:30
Tanmoy Sarkar
1827667cb2 test(companion): Assert HTTP worker path is unchanged
Add two arbiter regression tests. A worker exit is still reaped normally (tmp
closed, child_exit called) while a companion manager pid is registered, so the
companion reap branch does not swallow worker exits. And an HTTP worker is
still spawned and recorded as before when companions are configured, so the
companion config never touches the worker path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:08:29 +05:30
Tanmoy Sarkar
31e08aac58 feat(companion): Close Gunicorn-only fds in the manager child
The forked companion manager inherits the arbiter's HTTP listening sockets,
its wakeup pipe, and the worker heartbeat files, none of which the manager
uses. Close them in the child before running so the manager and the companions
it forks do not pin the arbiter's fds. The manager creates its own signal pipe
and control socket after the fork.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:50:52 +05:30
Tanmoy Sarkar
22431f24e6 feat(companion): Restart the manager on Gunicorn reload
Arbiter.reload (SIGHUP) now calls reload_companion_manager. A running manager
is sent SIGTERM so it drains its companions; the SIGCHLD reaper clears its pid
and manage_companion_manager respawns it from the freshly reloaded cfg. If
companions were added where none ran, a new manager starts immediately.

Restarting reuses the existing stop and respawn path; transactional
per-companion reread stays available separately through the control socket.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:32:59 +05:30
Tanmoy Sarkar
073a0b2e7d feat(companion): Shut down the manager from the arbiter
Arbiter.stop now signals the companion manager alongside the workers. It sends
the same SIGTERM (graceful) or SIGQUIT (immediate), waits the graceful_timeout
for both the workers and the manager to exit, then SIGKILLs whatever remains.
A graceful SIGTERM lets the manager stop its own companions before exiting.

stop_companion_manager(sig) signals the manager pid when it is running and
clears the pid on ESRCH; the SIGCHLD reaper clears it on a normal exit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:30:58 +05:30
Tanmoy Sarkar
457bc5a69a feat(companion): Spawn and reap the manager from the arbiter
Run the companion manager as a single arbiter child with its own
supervision loop, and host the config model with its loader.

config.py holds CompanionConfig (moved from process.py) and
build_companion_configs(cfg), which expands each companion_workers entry into
a CompanionConfig, filling omitted fields from the global companion_* settings.
It is also the reread config_loader. process.py keeps State and CompanionProcess.

CompanionManager.run() is the forked-child body: installs SIGCHLD/SIGTERM/SIGINT
via a self-pipe, brings up the control socket, starts every companion, then
select-waits on the socket and the pipe. Each tick reaps exits, retries backoff,
promotes past startsecs, and SIGKILLs companions past their stop deadline.
SIGTERM/SIGINT stop all companions and return.

Arbiter gains companion_manager_pid, manage_companion_manager (respawns the
manager when it is gone and companions are configured), spawn_companion_manager
(fork; child runs the loop), and reap detection that clears the pid on exit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 22:24:53 +05:30
Paul J. Dorn
4323027b1e drop long-default - coding: utf-8 2024-04-22 03:33:14 +02:00
unknown
48d670f087 update pylint version, and fix linter issues 2023-05-17 18:45:59 +03:00
Masashi SHIBATA
b15712924f Import unittest.mock unconditionally (#2050) 2019-05-28 16:09:44 +03:00
Marat
a8963ef1a5 Remove redundant super() arguments 2019-03-16 15:00:07 -07:00
Konstantin vz'One Enchant
927fb2ba02 Prevent removal unix socket for reuse_port (#1887)
If you have two (or more) instances of gunicorn that use `reuse-port`
and bind to single unix socket all work until one of gunicorn will
stopped. Because the first stopped removes unix socket file and other
instances can't longer process requests.
2018-10-02 13:25:35 +02:00
Benoit Chesneau
21ffa92be1 Merge pull request #1394 from jonashaag/master
Add child_exit() callback to configuration
2017-01-27 16:00:58 +01:00
Randall Leeds
0be7996885 Refactor socket activation and fd inheritance (#1310)
Track the use of systemd socket activation and gunicorn socket inheritance
in the arbiter. Unify the logic of creating gunicorn sockets from each of
these sources to always use the socket name to determine the type rather
than checking the configured addresses. The configured addresses are only
used when there is no inheritance from systemd or a parent arbiter.

Fix #1298
2016-12-27 14:01:20 -08:00
Jonas Haag
53fd1c1071 Add child_exit() callback
This is similar to worker_exit() in that it is called just after a
worker has terminated, but it's called in the Gunicorn *master* process,
not the *child* process.
2016-11-25 12:16:23 +01:00
Jonas Haag
b3c4260706 Add test for worker_exit() 2016-11-25 12:16:23 +01:00
benoitc
418f140445 remove file locking
This changes improve the binary upgrade behaviour using USR2:

- only one binary upgrade can happen at a time: the old arbiter needs to be
  killed to promote the new arbiter.
- if a new arbiter is already spawned, until one is killed USR2 has no action
- if a new arbiter has been spawned, the unix socket won't be unlinked
- until the old arbiter have been killed the newly created pidfile has the name
  <pidfile>.2 and the name Master.2 .

Note: there is no dialog between both arbiters to handle this features.
Instead they will supervise each others until one is killed. So isolation is
still guaranted.

fix #1267
2016-05-20 15:42:55 +02:00
benoitc
8a6748ee65 fix unix socket locking
This change add proper file locking to gunicorn. By default "gunicorn.lock" is created in the temporary directory when a unix socket is bound.  In case someone want to fix the lock file path or use multiple gunicorn instance the "--lock-file" setting can be used to set the path of this file.

fix #1259
2016-05-14 22:03:40 +02:00
Randall Leeds
39cecbc8e9 [arbiter] close sockets on shutdown
Close all the listeners when the arbiter shuts down. By doing so,
workers can close the socket at the beginning of a graceful shut
down thereby informing the operating system that the socket can
be cleaned up. With this change, graceful exits with such workers
will refuse new connections while draining, allowing load balancers
to respond more quickly and avoiding leaving connections dangling
in the listen backlog, unaccepted.

Ref #922
2016-03-13 16:47:23 -07:00
Berker Peksag
9475e2625e Rename test files. 2015-07-03 07:46:22 +03:00