-
-
Notifications
You must be signed in to change notification settings - Fork 903
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
root: handle SIGHUP and SIGUSR2, healthcheck gunicorn
This is the first step to handle configuration reloading. With those changes, it is already possible to do so, by sending a SIGUSR2 signal to the Go server process. The next step would be to watch for changes to configuration files and call the Restart function of the GoUnicorn instance. SIGHUP is catched by the go server and forwarded as-is to gunicorn, which causes it to restart its workers. However, that does not trigger a reload of the Django settings, probably because they are already loaded in the master, before creating any of the worker instances. SIGUSR2, however, can be used to spawn a new gunicorn master process, but handling it is a bit trickier. Please refer to Gunicorn's documentation[0] for details, especially the "Upgrading to a new binary on the fly" section. As we are now effectively killing the gunicorn processed launched by the server, we need to handle some sort of check to make sure it is still running. That's done by using the already existing healthchecks, making them useful not only for the application start, but also for its lifetime. If a check is failed too many times in a given time period, the gunicorn processed is killed (if necessary) and then restarted. [0] https://docs.gunicorn.org/en/20.1.0/signals.html Other relevant links and documentation: Python library handling the processing swaping upon a SIGUSR2: https://github.com/flupke/rainbow-saddle/ Golang cannot easily check if a process exists on Unix systems: golang/go#34396 Signed-off-by: Marc 'risson' Schmitt <[email protected]>
- Loading branch information
Showing
3 changed files
with
163 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package utils | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"os" | ||
"syscall" | ||
) | ||
|
||
func FindProcess(pid int) (*os.Process, error) { | ||
if pid <= 0 { | ||
return nil, fmt.Errorf("invalid pid %v", pid) | ||
} | ||
// The error doesn't mean anything on Unix systems, let's just check manually | ||
// that the new gunicorn master has properly started | ||
// https://github.com/golang/go/issues/34396 | ||
proc, err := os.FindProcess(int(pid)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
err = proc.Signal(syscall.Signal(0)) | ||
if err == nil { | ||
return proc, nil | ||
} | ||
if errors.Is(err, os.ErrProcessDone) { | ||
return nil, nil | ||
} | ||
errno, ok := err.(syscall.Errno) | ||
if !ok { | ||
return nil, err | ||
} | ||
switch errno { | ||
case syscall.ESRCH: | ||
return nil, nil | ||
case syscall.EPERM: | ||
return proc, nil | ||
} | ||
return nil, err | ||
} |