Skip to content

Commit e3f22ad

Browse files
zeripathsapk
authored andcommitted
Graceful: Allow graceful restart for unix sockets (#9113)
Previously we could not handle graceful restarts for http over unix sockets. These can now be handled.
1 parent bb2c0c3 commit e3f22ad

File tree

4 files changed

+31
-30
lines changed

4 files changed

+31
-30
lines changed

cmd/web.go

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func runHTTPRedirector() {
6060
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
6161
})
6262

63-
var err = runHTTP(source, context2.ClearHandler(handler))
63+
var err = runHTTP("tcp", source, context2.ClearHandler(handler))
6464

6565
if err != nil {
6666
log.Fatal("Failed to start port redirection: %v", err)
@@ -77,12 +77,12 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
7777
go func() {
7878
log.Info("Running Let's Encrypt handler on %s", setting.HTTPAddr+":"+setting.PortToRedirect)
7979
// all traffic coming into HTTP will be redirect to HTTPS automatically (LE HTTP-01 validation happens here)
80-
var err = runHTTP(setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)))
80+
var err = runHTTP("tcp", setting.HTTPAddr+":"+setting.PortToRedirect, certManager.HTTPHandler(http.HandlerFunc(runLetsEncryptFallbackHandler)))
8181
if err != nil {
8282
log.Fatal("Failed to start the Let's Encrypt handler on port %s: %v", setting.PortToRedirect, err)
8383
}
8484
}()
85-
return runHTTPSWithTLSConfig(listenAddr, certManager.TLSConfig(), context2.ClearHandler(m))
85+
return runHTTPSWithTLSConfig("tcp", listenAddr, certManager.TLSConfig(), context2.ClearHandler(m))
8686
}
8787

8888
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
@@ -171,7 +171,7 @@ func runWeb(ctx *cli.Context) error {
171171
switch setting.Protocol {
172172
case setting.HTTP:
173173
NoHTTPRedirector()
174-
err = runHTTP(listenAddr, context2.ClearHandler(m))
174+
err = runHTTP("tcp", listenAddr, context2.ClearHandler(m))
175175
case setting.HTTPS:
176176
if setting.EnableLetsEncrypt {
177177
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, context2.ClearHandler(m))
@@ -182,7 +182,7 @@ func runWeb(ctx *cli.Context) error {
182182
} else {
183183
NoHTTPRedirector()
184184
}
185-
err = runHTTPS(listenAddr, setting.CertFile, setting.KeyFile, context2.ClearHandler(m))
185+
err = runHTTPS("tcp", listenAddr, setting.CertFile, setting.KeyFile, context2.ClearHandler(m))
186186
case setting.FCGI:
187187
NoHTTPRedirector()
188188
// FCGI listeners are provided as stdin - this is orthogonal to the LISTEN_FDS approach
@@ -200,25 +200,8 @@ func runWeb(ctx *cli.Context) error {
200200
}()
201201
err = fcgi.Serve(listener, context2.ClearHandler(m))
202202
case setting.UnixSocket:
203-
// This could potentially be inherited using LISTEN_FDS but currently
204-
// these cannot be inherited
205203
NoHTTPRedirector()
206-
NoMainListener()
207-
if err := os.Remove(listenAddr); err != nil && !os.IsNotExist(err) {
208-
log.Fatal("Failed to remove unix socket directory %s: %v", listenAddr, err)
209-
}
210-
var listener *net.UnixListener
211-
listener, err = net.ListenUnix("unix", &net.UnixAddr{Name: listenAddr, Net: "unix"})
212-
if err != nil {
213-
break // Handle error after switch
214-
}
215-
216-
// FIXME: add proper implementation of signal capture on all protocols
217-
// execute this on SIGTERM or SIGINT: listener.Close()
218-
if err = os.Chmod(listenAddr, os.FileMode(setting.UnixSocketPermission)); err != nil {
219-
log.Fatal("Failed to set permission of unix socket: %v", err)
220-
}
221-
err = http.Serve(listener, context2.ClearHandler(m))
204+
err = runHTTP("unix", listenAddr, context2.ClearHandler(m))
222205
default:
223206
log.Fatal("Invalid protocol: %s", setting.Protocol)
224207
}

cmd/web_graceful.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ import (
1111
"code.gitea.io/gitea/modules/graceful"
1212
)
1313

14-
func runHTTP(listenAddr string, m http.Handler) error {
15-
return graceful.HTTPListenAndServe("tcp", listenAddr, m)
14+
func runHTTP(network, listenAddr string, m http.Handler) error {
15+
return graceful.HTTPListenAndServe(network, listenAddr, m)
1616
}
1717

18-
func runHTTPS(listenAddr, certFile, keyFile string, m http.Handler) error {
19-
return graceful.HTTPListenAndServeTLS("tcp", listenAddr, certFile, keyFile, m)
18+
func runHTTPS(network, listenAddr, certFile, keyFile string, m http.Handler) error {
19+
return graceful.HTTPListenAndServeTLS(network, listenAddr, certFile, keyFile, m)
2020
}
2121

22-
func runHTTPSWithTLSConfig(listenAddr string, tlsConfig *tls.Config, m http.Handler) error {
23-
return graceful.HTTPListenAndServeTLSConfig("tcp", listenAddr, tlsConfig, m)
22+
func runHTTPSWithTLSConfig(network, listenAddr string, tlsConfig *tls.Config, m http.Handler) error {
23+
return graceful.HTTPListenAndServeTLSConfig(network, listenAddr, tlsConfig, m)
2424
}
2525

2626
// NoHTTPRedirector tells our cleanup routine that we will not be using a fallback http redirector

modules/graceful/net_unix.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"sync"
1717

1818
"code.gitea.io/gitea/modules/log"
19+
"code.gitea.io/gitea/modules/setting"
1920
)
2021

2122
const (
@@ -165,15 +166,27 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener,
165166
if isSameAddr(l.Addr(), address) {
166167
providedListeners = append(providedListeners[:i], providedListeners[i+1:]...)
167168
activeListeners = append(activeListeners, l)
168-
return l.(*net.UnixListener), nil
169+
unixListener := l.(*net.UnixListener)
170+
unixListener.SetUnlinkOnClose(true)
171+
return unixListener, nil
169172
}
170173
}
171174

172175
// make a fresh listener
176+
if err := os.Remove(address.Name); err != nil && !os.IsNotExist(err) {
177+
return nil, fmt.Errorf("Failed to remove unix socket %s: %v", address.Name, err)
178+
}
179+
173180
l, err := net.ListenUnix(network, address)
174181
if err != nil {
175182
return nil, err
176183
}
184+
185+
fileMode := os.FileMode(setting.UnixSocketPermission)
186+
if err = os.Chmod(address.Name, fileMode); err != nil {
187+
return nil, fmt.Errorf("Failed to set permission of unix socket to %s: %v", fileMode.String(), err)
188+
}
189+
177190
activeListeners = append(activeListeners, l)
178191
return l, nil
179192
}

modules/graceful/restart_unix.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package graceful
99

1010
import (
1111
"fmt"
12+
"net"
1213
"os"
1314
"os/exec"
1415
"strings"
@@ -48,6 +49,10 @@ func RestartProcess() (int, error) {
4849
if err != nil {
4950
return 0, err
5051
}
52+
53+
if unixListener, ok := l.(*net.UnixListener); ok {
54+
unixListener.SetUnlinkOnClose(false)
55+
}
5156
// Remember to close these at the end.
5257
defer files[i].Close()
5358
}

0 commit comments

Comments
 (0)