mirror of
https://github.com/cnrancher/kube-explorer.git
synced 2025-08-25 17:48:50 +00:00
fix: Should handle stale socket file
Added a lock file to hold make sure that it's safe to rebuild socket file
This commit is contained in:
parent
8d1433b07d
commit
4c1db385fc
@ -13,11 +13,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Serve(ctx context.Context, server *server.Server) error {
|
func Serve(ctx context.Context, server *server.Server) error {
|
||||||
listener, ipOrPath, err := ensureListener()
|
listener, ipOrPath, err := ensureListener(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if listener != nil {
|
if listener != nil {
|
||||||
|
defer listener.Close()
|
||||||
return serveSocket(ctx, ipOrPath, listener, server)
|
return serveSocket(ctx, ipOrPath, listener, server)
|
||||||
}
|
}
|
||||||
return server.ListenAndServe(ctx, config.Steve.HTTPSListenPort, config.Steve.HTTPListenPort, &dynamicserver.ListenOpts{
|
return server.ListenAndServe(ctx, config.Steve.HTTPSListenPort, config.Steve.HTTPListenPort, &dynamicserver.ListenOpts{
|
||||||
@ -45,7 +46,6 @@ func serveSocket(ctx context.Context, socketPath string, listener net.Listener,
|
|||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
_ = socketServer.Shutdown(context.Background())
|
_ = socketServer.Shutdown(context.Background())
|
||||||
_ = listener.Close()
|
|
||||||
}()
|
}()
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
|
@ -4,14 +4,44 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/cnrancher/kube-explorer/internal/config"
|
"github.com/cnrancher/kube-explorer/internal/config"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureListener() (net.Listener, string, error) {
|
var _ net.Listener = &closerListener{}
|
||||||
|
|
||||||
|
type closerListener struct {
|
||||||
|
listener net.Listener
|
||||||
|
lockFile *os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *closerListener) Accept() (net.Conn, error) {
|
||||||
|
return l.listener.Accept()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *closerListener) Close() error {
|
||||||
|
return errors.Join(
|
||||||
|
l.listener.Close(),
|
||||||
|
l.lockFile.Close(),
|
||||||
|
os.RemoveAll(l.lockFile.Name()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *closerListener) Addr() net.Addr {
|
||||||
|
return l.listener.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureListener(ctx context.Context) (net.Listener, string, error) {
|
||||||
if config.BindAddress == "" {
|
if config.BindAddress == "" {
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
@ -25,9 +55,45 @@ func ensureListener() (net.Listener, string, error) {
|
|||||||
case "tcp":
|
case "tcp":
|
||||||
return nil, u.Host, nil
|
return nil, u.Host, nil
|
||||||
case "unix":
|
case "unix":
|
||||||
listener, err := net.Listen("unix", u.Path)
|
listener, err := createCloserListener(ctx, u.Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", err
|
||||||
|
}
|
||||||
return listener, u.Path, err
|
return listener, u.Path, err
|
||||||
default:
|
default:
|
||||||
return nil, "", fmt.Errorf("Unsupported scheme %s, only tcp and unix are supported in UNIX OS", u.Scheme)
|
return nil, "", fmt.Errorf("Unsupported scheme %s, only tcp and unix are supported in UNIX OS", u.Scheme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createCloserListener(ctx context.Context, socketPath string) (net.Listener, error) {
|
||||||
|
lockFilePath := getLockFileName(socketPath)
|
||||||
|
lockFile, err := os.OpenFile(lockFilePath, os.O_RDONLY|os.O_CREATE, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lockErr := syscall.Flock(int(lockFile.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
|
||||||
|
if lockErr != nil {
|
||||||
|
return nil, fmt.Errorf("Socket file %s is in use, exiting", socketPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(socketPath); err == nil {
|
||||||
|
logrus.Infof("Removing stale socket file %s", socketPath)
|
||||||
|
_ = os.Remove(socketPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lc net.ListenConfig
|
||||||
|
listener, err := lc.Listen(ctx, "unix", socketPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &closerListener{
|
||||||
|
listener: listener,
|
||||||
|
lockFile: lockFile,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLockFileName(socketPath string) string {
|
||||||
|
return strings.TrimSuffix(socketPath, filepath.Ext(socketPath)) + ".lock"
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -12,7 +13,7 @@ import (
|
|||||||
"github.com/cnrancher/kube-explorer/internal/config"
|
"github.com/cnrancher/kube-explorer/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureListener() (net.Listener, string, error) {
|
func ensureListener(_ context.Context) (net.Listener, string, error) {
|
||||||
if config.BindAddress == "" {
|
if config.BindAddress == "" {
|
||||||
return nil, "", nil
|
return nil, "", nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user