diff options
| author | Shulhan <ms@kilabit.info> | 2022-09-01 21:25:35 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2022-09-01 21:25:57 +0700 |
| commit | 704be0550ef67a4827b2d9b1c8656f4a21d2779c (patch) | |
| tree | 807ad2d68e2e38d7992681be045b9b86f34be554 | |
| parent | 91fce8ab6ce4c6f9722ac2af15fca33600e45abf (diff) | |
| download | pakakeh.go-704be0550ef67a4827b2d9b1c8656f4a21d2779c.tar.xz | |
lib/memfs: fix SIGSEGV when node is deleted when being watched
The panic is caused by the item in slice of Childs is being
removed during iteration.
To fix this, we remove the childs on the second iteration after
we remove any sub directories inside them.
| -rw-r--r-- | lib/memfs/dirwatcher.go | 39 | ||||
| -rw-r--r-- | lib/memfs/node.go | 3 |
2 files changed, 23 insertions, 19 deletions
diff --git a/lib/memfs/dirwatcher.go b/lib/memfs/dirwatcher.go index e519fe7a..8cc3e75f 100644 --- a/lib/memfs/dirwatcher.go +++ b/lib/memfs/dirwatcher.go @@ -154,14 +154,18 @@ func (dw *DirWatcher) mapSubdirs(node *Node) { } } -// unmapSubdirs find sub directories in node's childrens, recursively and -// remove it from map of node. +// unmapSubdirs remove the node from dw's fs including its childs. func (dw *DirWatcher) unmapSubdirs(node *Node) { - for _, child := range node.Childs { + var ( + child *Node + ) + for _, child = range node.Childs { if child.IsDir() { delete(dw.dirs, child.Path) dw.unmapSubdirs(child) } + } + for _, child = range node.Childs { dw.fs.RemoveChild(node, child) } if node.IsDir() { @@ -250,22 +254,22 @@ func (dw *DirWatcher) onContentChange(node *Node) { State: FileStateCreated, } - //nolint - select { - case dw.qchanges <- ns: - } - if newChild.IsDir() { dw.dirs[newChild.Path] = newChild dw.mapSubdirs(newChild) dw.onContentChange(newChild) - continue + } else { + // Start watching the file for modification. + _, err = newWatcher(node, newInfo, dw.Delay, dw.qFileChanges) + if err != nil { + log.Printf("%s: %s", logp, err) + continue + } } - // Start watching the file for modification. - _, err = newWatcher(node, newInfo, dw.Delay, dw.qFileChanges) - if err != nil { - log.Printf("%s: %s", logp, err) + //nolint + select { + case dw.qchanges <- ns: } } } @@ -393,13 +397,10 @@ func (dw *DirWatcher) start() { dw.onModified(dw.root, fi) continue } - if dw.root.ModTime().Equal(fi.ModTime()) { - dw.processSubdirs() - continue + if !dw.root.ModTime().Equal(fi.ModTime()) { + dw.fs.Update(dw.root, fi) + dw.onContentChange(dw.root) } - - dw.fs.Update(dw.root, fi) - dw.onContentChange(dw.root) dw.processSubdirs() case ns = <-dw.qFileChanges: diff --git a/lib/memfs/node.go b/lib/memfs/node.go index 76720f66..817326a9 100644 --- a/lib/memfs/node.go +++ b/lib/memfs/node.go @@ -419,6 +419,9 @@ func (node *Node) packAsJson(buf *bytes.Buffer, depth int) { // removeChild remove a children node from list. If child is not exist, it // will return nil. func (node *Node) removeChild(child *Node) *Node { + if child == nil { + return nil + } for x := 0; x < len(node.Childs); x++ { if node.Childs[x] != child { continue |
