serve: fix VFS instance leaks on server startup failures and shutdown
This commit is contained in:
committed by
Nick Craig-Wood
parent
45ddf3a5f2
commit
216d2a8c76
@@ -244,6 +244,7 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
|
||||
}
|
||||
listener, err := net.Listen(network, s.httpListenAddr)
|
||||
if err != nil {
|
||||
s.vfs.Shutdown()
|
||||
return nil, err
|
||||
}
|
||||
s.HTTPConn = listener
|
||||
@@ -402,6 +403,7 @@ func (s *server) Wait() {
|
||||
// Shutdown the DLNA server
|
||||
func (s *server) Shutdown() error {
|
||||
err := s.HTTPConn.Close()
|
||||
s.vfs.Shutdown()
|
||||
close(s.waitChan)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to shutdown DLNA server: %w", err)
|
||||
|
||||
@@ -354,7 +354,12 @@ func (d *driver) CheckPasswd(sctx *ftp.Context, user, pass string) (ok bool, err
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Get the VFS for this connection
|
||||
// getVFS returns the VFS for this connection.
|
||||
//
|
||||
// In proxy mode, getVFS calls proxy.Call on each FTP command which refreshes
|
||||
// the proxy cache timer (like http/webdav). Therefore, connection-level pinning
|
||||
// is not used; only individual transfers exceeding the cache expiry window
|
||||
// could be affected.
|
||||
func (d *driver) getVFS(sctx *ftp.Context) (VFS *vfs.VFS, err error) {
|
||||
if !d.provider.IsProxy() {
|
||||
// If no proxy always use the same VFS
|
||||
|
||||
+21
-2
@@ -82,6 +82,17 @@ func AddFlags(flagSet *pflag.FlagSet) {
|
||||
flags.AddFlagsFromOptions(flagSet, "", OptionsInfo)
|
||||
}
|
||||
|
||||
type nfsHandler struct {
|
||||
*Server
|
||||
vfs *vfs.VFS
|
||||
}
|
||||
|
||||
func (h *nfsHandler) Shutdown() error {
|
||||
err := h.Server.Shutdown()
|
||||
h.vfs.Shutdown()
|
||||
return err
|
||||
}
|
||||
|
||||
func init() {
|
||||
vfsflags.AddFlags(Command.Flags())
|
||||
AddFlags(Command.Flags())
|
||||
@@ -98,10 +109,16 @@ func init() {
|
||||
var opt = Opt // set default opts
|
||||
err = rc.ParseOptions(in, "opt", &opt)
|
||||
if err != nil {
|
||||
VFS.Shutdown()
|
||||
return nil, err
|
||||
}
|
||||
// Create server
|
||||
return NewServer(ctx, VFS, &opt)
|
||||
s, err := NewServer(ctx, VFS, &opt)
|
||||
if err != nil {
|
||||
VFS.Shutdown()
|
||||
return nil, err
|
||||
}
|
||||
return &nfsHandler{Server: s, vfs: VFS}, nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -111,7 +128,9 @@ func Run(command *cobra.Command, args []string) {
|
||||
cmd.CheckArgs(1, 1, command, args)
|
||||
f = cmd.NewFsSrc(args)
|
||||
cmd.Run(false, true, command, func() error {
|
||||
s, err := NewServer(context.Background(), vfs.New(context.Background(), f, &vfscommon.Opt), &Opt)
|
||||
VFS := vfs.New(context.Background(), f, &vfscommon.Opt)
|
||||
defer VFS.Shutdown()
|
||||
s, err := NewServer(context.Background(), VFS, &Opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ func newServer(ctx context.Context, f fs.Fs, opt *Options, vfsOpt *vfscommon.Opt
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if w.backend != nil {
|
||||
w.backend.stopReaper()
|
||||
}
|
||||
w.provider.Shutdown()
|
||||
}
|
||||
}()
|
||||
@@ -168,6 +171,7 @@ func (w *Server) Addr() net.Addr {
|
||||
|
||||
// Shutdown the server
|
||||
func (w *Server) Shutdown() error {
|
||||
w.backend.stopReaper()
|
||||
err := w.server.Shutdown()
|
||||
w.provider.Shutdown()
|
||||
return err
|
||||
|
||||
@@ -99,6 +99,13 @@ func (s *server) acceptConnection(nConn net.Conn) {
|
||||
// Discard all global out-of-band Requests
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
||||
if sshConn.Permissions != nil && sshConn.Permissions.Extensions != nil {
|
||||
if vfsKey := sshConn.Permissions.Extensions["_vfsKey"]; vfsKey != "" {
|
||||
s.provider.Pin(vfsKey)
|
||||
defer s.provider.Unpin(vfsKey)
|
||||
}
|
||||
}
|
||||
|
||||
c := &conn{
|
||||
what: what,
|
||||
vfs: s.getVFS(what, sshConn),
|
||||
@@ -111,7 +118,7 @@ func (s *server) acceptConnection(nConn net.Conn) {
|
||||
c.handlers = newVFSHandler(c.vfs)
|
||||
|
||||
// Accept all channels
|
||||
go c.handleChannels(chans)
|
||||
c.handleChannels(chans)
|
||||
}
|
||||
|
||||
// Accept connections and call them in a go routine
|
||||
|
||||
Reference in New Issue
Block a user