summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2022-09-01 21:25:35 +0700
committerShulhan <ms@kilabit.info>2022-09-01 21:25:57 +0700
commit704be0550ef67a4827b2d9b1c8656f4a21d2779c (patch)
tree807ad2d68e2e38d7992681be045b9b86f34be554
parent91fce8ab6ce4c6f9722ac2af15fca33600e45abf (diff)
downloadpakakeh.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.go39
-rw-r--r--lib/memfs/node.go3
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