]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Improve Closing (#559)
authorZilog8 <zeuscoding@gmail.com>
Sun, 5 Sep 2021 01:33:41 +0000 (21:33 -0400)
committerGitHub <noreply@github.com>
Sun, 5 Sep 2021 01:33:41 +0000 (11:33 +1000)
- Prevent double-closing in cmd/torrent
- Move async closing from storage to torrents, and wait on them to finish tidying up before returning/exiting.

client.go
cmd/torrent/main.go
torrent.go

index aea3677e9b4dd1c3d639511dfcacc5e712e511fe..251de308275e1f465d52d43f188779ef5d8c8b59 100644 (file)
--- a/client.go
+++ b/client.go
@@ -411,11 +411,13 @@ func (cl *Client) eachDhtServer(f func(DhtServer)) {
 // Stops the client. All connections to peers are closed and all activity will
 // come to a halt.
 func (cl *Client) Close() {
+       var closeGroup sync.WaitGroup //WaitGroup for any concurrent cleanup to complete before returning.
+       defer closeGroup.Wait() //defer is LIFO. We want to Wait() after cl.unlock()
        cl.lock()
        defer cl.unlock()
        cl.closed.Set()
        for _, t := range cl.torrents {
-               t.close()
+               t.close(&closeGroup)
        }
        for i := range cl.onClose {
                cl.onClose[len(cl.onClose)-1-i]()
@@ -1252,7 +1254,9 @@ func (cl *Client) dropTorrent(infoHash metainfo.Hash) (err error) {
                err = fmt.Errorf("no such torrent")
                return
        }
-       err = t.close()
+       var wg sync.WaitGroup
+       defer wg.Wait()
+       err = t.close(&wg)
        if err != nil {
                panic(err)
        }
index a11373f7bb5326a041686b2a223d6bd439a9d0e3..c24310bd988875ea27f40249bef237e0fc406577 100644 (file)
@@ -11,6 +11,7 @@ import (
        "os"
        "os/signal"
        "strings"
+       "sync"
        "syscall"
        "time"
 
@@ -332,11 +333,12 @@ func downloadErr() error {
        if err != nil {
                return xerrors.Errorf("creating client: %v", err)
        }
-       defer client.Close()
+       var clientClose sync.Once //In certain situations, close was being called more than once.
+       defer clientClose.Do(client.Close)
        go exitSignalHandlers(&stop)
        go func() {
                <-stop.C()
-               client.Close()
+               clientClose.Do(client.Close)
        }()
 
        // Write status on the root path on the default HTTP muxer. This will be bound to localhost
index 35d9a42914a05e7d2d11932f267ac30c328c57b6..70a8a9e1b7eb634cea7f8324389f4541033a8b8b 100644 (file)
@@ -789,14 +789,19 @@ func (t *Torrent) numPiecesCompleted() (num pieceIndex) {
        return pieceIndex(t._completedPieces.GetCardinality())
 }
 
-func (t *Torrent) close() (err error) {
+func (t *Torrent) close(wg *sync.WaitGroup) (err error) {
        t.closed.Set()
        if t.storage != nil {
+               wg.Add(1)
                go func() {
+                       defer wg.Done()
                        t.storageLock.Lock()
                        defer t.storageLock.Unlock()
                        if f := t.storage.Close; f != nil {
-                               f()
+                               err1 := f()
+                               if err1 != nil {
+                                       t.logger.WithDefaultLevel(log.Warning).Printf("error closing storage: %v", err1)
+                               }
                        }
                }()
        }