|
1 | 1 | // Copyright 2015 Light Code Labs, LLC |
2 | 2 | // |
| 3 | +// Copyright 2024 MWS |
| 4 | +// |
3 | 5 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | 6 | // you may not use this file except in compliance with the License. |
5 | 7 | // You may obtain a copy of the License at |
@@ -218,22 +220,22 @@ func (i *Instance) Restart(newCaddyfile Input) (*Instance, error) { |
218 | 220 | } |
219 | 221 |
|
220 | 222 | // Add file descriptors of all the sockets that are capable of it |
221 | | - restartFds := make(map[string]restartTriple) |
| 223 | + restartFds := make(map[string][]restartTriple) |
222 | 224 | for _, s := range i.servers { |
223 | 225 | gs, srvOk := s.server.(GracefulServer) |
224 | 226 | ln, lnOk := s.listener.(Listener) |
225 | 227 | pc, pcOk := s.packet.(PacketConn) |
226 | 228 | if srvOk { |
227 | 229 | if lnOk && pcOk { |
228 | | - restartFds[gs.Address()] = restartTriple{server: gs, listener: ln, packet: pc} |
| 230 | + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, listener: ln, packet: pc}) |
229 | 231 | continue |
230 | 232 | } |
231 | 233 | if lnOk { |
232 | | - restartFds[gs.Address()] = restartTriple{server: gs, listener: ln} |
| 234 | + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, listener: ln}) |
233 | 235 | continue |
234 | 236 | } |
235 | 237 | if pcOk { |
236 | | - restartFds[gs.Address()] = restartTriple{server: gs, packet: pc} |
| 238 | + restartFds[gs.Address()] = append(restartFds[gs.Address()], restartTriple{server: gs, packet: pc}) |
237 | 239 | continue |
238 | 240 | } |
239 | 241 | } |
@@ -484,7 +486,7 @@ func Start(cdyfile Input) (*Instance, error) { |
484 | 486 | return inst, nil |
485 | 487 | } |
486 | 488 |
|
487 | | -func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]restartTriple) error { |
| 489 | +func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string][]restartTriple) error { |
488 | 490 | // save this instance in the list now so that |
489 | 491 | // plugins can access it if need be, for example |
490 | 492 | // the caddytls package, so it can perform cert |
@@ -684,7 +686,7 @@ func executeDirectives(inst *Instance, filename string, |
684 | 686 | return nil |
685 | 687 | } |
686 | 688 |
|
687 | | -func startServers(serverList []Server, inst *Instance, restartFds map[string]restartTriple) error { |
| 689 | +func startServers(serverList []Server, inst *Instance, restartFds map[string][]restartTriple) error { |
688 | 690 | errChan := make(chan error, len(serverList)) |
689 | 691 |
|
690 | 692 | // used for signaling to error logging goroutine to terminate |
@@ -734,7 +736,16 @@ func startServers(serverList []Server, inst *Instance, restartFds map[string]res |
734 | 736 | // reuse the listener for a graceful restart. |
735 | 737 | if gs, ok := s.(GracefulServer); ok && restartFds != nil { |
736 | 738 | addr := gs.Address() |
737 | | - if old, ok := restartFds[addr]; ok { |
| 739 | + // Multiple servers may use the same addr (SO_REUSEPORT option set), so it's important to ensure |
| 740 | + // that we don't reuse the same listener/packetconn. |
| 741 | + // We'll create new listeners in case there are no more available triples for the same address. |
| 742 | + if triples, ok := restartFds[addr]; ok && len(triples) > 0 { |
| 743 | + // Take first available triple |
| 744 | + old := triples[0] |
| 745 | + // Remove reused triple from restartFds |
| 746 | + triples[0] = triples[len(triples)-1] |
| 747 | + restartFds[addr] = triples[:len(triples)-1] |
| 748 | + |
738 | 749 | // listener |
739 | 750 | if old.listener != nil { |
740 | 751 | file, err := old.listener.File() |
|
0 commit comments