Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 13, 05:30 UTC
core: Eliminate unnecessary shutdown delay on Unix (#5413)
* core: Eliminate unnecessary shutdown delay on Unix Fix #5393, alternate to #5405 * Comments, cleanup, adjust logs * Fix build constraint
Matt Holt committed
Mar 2, 2023 at 21:00 UTC
99d47050e97a8ccac2aad3bda46be46d4fec85ed
4 files changed
+36
-13
go.mod
+1
-1
@@ -1,6 +1,6 @@
1
module github.com/caddyserver/caddy/v2
2
3
-go 1.18
3
+go 1.19
4
5
require (
6
github.com/BurntSushi/toml v1.2.1
listen.go
+1
-4
@@ -12,10 +12,7 @@
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
-// TODO: Go 1.19 introduced the "unix" build tag. We have to support Go 1.18 until Go 1.20 is released.
16
-// When Go 1.19 is our minimum, change this build tag to simply "!unix".
17
-// (see similar change needed in listen_unix.go)
18
-//go:build !(aix || android || darwin || dragonfly || freebsd || hurd || illumos || ios || linux || netbsd || openbsd || solaris)
15
+//go:build !unix
16
17
package caddy
18
listen_unix.go
+31
-5
@@ -12,10 +12,10 @@
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
-// TODO: Go 1.19 introduced the "unix" build tag. We have to support Go 1.18 until Go 1.20 is released.
16
-// When Go 1.19 is our minimum, remove this build tag, since "_unix" in the filename will do this.
17
-// (see also change needed in listen.go)
18
-//go:build aix || android || darwin || dragonfly || freebsd || hurd || illumos || ios || linux || netbsd || openbsd || solaris
15
+// Even though the filename ends in _unix.go, we still have to specify the
16
+// build constraint here, because the filename convention only works for
17
+// literal GOOS values, and "unix" is a shortcut unique to build tags.
18
+//go:build unix
19
20
package caddy
21
@@ -98,7 +98,19 @@ func listenTCPOrUnix(ctx context.Context, lnKey string, network, address string,
98
}
99
return reusePort(network, address, c)
100
}
101
- return config.Listen(ctx, network, address)
101
+
102
+ // even though SO_REUSEPORT lets us bind the socket multiple times,
103
+ // we still put it in the listenerPool so we can count how many
104
+ // configs are using this socket; necessary to ensure we can know
105
+ // whether to enforce shutdown delays, for example (see #5393).
106
+ ln, err := config.Listen(ctx, network, address)
107
+ if err == nil {
108
+ listenerPool.LoadOrStore(lnKey, nil)
109
+ }
110
+
111
+ // lightly wrap the listener so that when it is closed,
112
+ // we can decrement the usage pool counter
113
+ return deleteListener{ln, lnKey}, err
114
}
115
116
// reusePort sets SO_REUSEPORT. Ineffective for unix sockets.
@@ -116,3 +128,17 @@ func reusePort(network, address string, conn syscall.RawConn) error {
128
}
129
})
130
}
131
+
132
+// deleteListener is a type that simply deletes itself
133
+// from the listenerPool when it closes. It is used
134
+// solely for the purpose of reference counting (i.e.
135
+// counting how many configs are using a given socket).
136
+type deleteListener struct {
137
+ net.Listener
138
+ lnKey string
139
+}
140
+
141
+func (dl deleteListener) Close() error {
142
+ _, _ = listenerPool.Delete(dl.lnKey)
143
+ return dl.Listener.Close()
144
+}
modules/caddyhttp/app.go
+3
-3
@@ -517,7 +517,7 @@ func (app *App) Stop() error {
517
518
// honor scheduled/delayed shutdown time
519
if delay {
520
- app.logger.Debug("shutdown scheduled",
520
+ app.logger.Info("shutdown scheduled",
521
zap.Duration("delay_duration", time.Duration(app.ShutdownDelay)),
522
zap.Time("time", scheduledTime))
523
time.Sleep(time.Duration(app.ShutdownDelay))
@@ -528,9 +528,9 @@ func (app *App) Stop() error {
528
var cancel context.CancelFunc
529
ctx, cancel = context.WithTimeout(ctx, time.Duration(app.GracePeriod))
530
defer cancel()
531
- app.logger.Debug("servers shutting down; grace period initiated", zap.Duration("duration", time.Duration(app.GracePeriod)))
531
+ app.logger.Info("servers shutting down; grace period initiated", zap.Duration("duration", time.Duration(app.GracePeriod)))
532
} else {
533
- app.logger.Debug("servers shutting down with eternal grace period")
533
+ app.logger.Info("servers shutting down with eternal grace period")
534
}
535
536
// goroutines aren't guaranteed to be scheduled right away,