Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-ds-flatfs
Commits
dc81160a
Unverified
Commit
dc81160a
authored
Dec 17, 2018
by
Steven Allen
Committed by
GitHub
Dec 17, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #51 from ipfs/fix/query-goroutine-leak
fix a goroutine leak killing the gateways
parents
bbeee3c3
3c828de2
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
68 additions
and
14 deletions
+68
-14
.travis.yml
.travis.yml
+1
-1
flatfs.go
flatfs.go
+30
-13
flatfs_test.go
flatfs_test.go
+31
-0
package.json
package.json
+6
-0
No files found.
.travis.yml
View file @
dc81160a
...
...
@@ -7,7 +7,7 @@ sudo: false
language
:
go
go
:
-
1.
9
.x
-
1.
11
.x
install
:
-
make deps
...
...
flatfs.go
View file @
dc81160a
...
...
@@ -19,6 +19,7 @@ import (
"github.com/ipfs/go-datastore"
"github.com/ipfs/go-datastore/query"
"github.com/jbenet/goprocess"
logging
"github.com/ipfs/go-log"
)
...
...
@@ -631,18 +632,25 @@ func (fs *Datastore) Query(q query.Query) (query.Results, error) {
return
nil
,
errors
.
New
(
"flatfs only supports listing all keys in random order"
)
}
reschan
:=
make
(
chan
query
.
Result
,
query
.
KeysOnlyBufSize
)
go
func
()
{
defer
close
(
reschan
)
err
:=
fs
.
walkTopLevel
(
fs
.
path
,
reschan
)
if
err
!=
nil
{
reschan
<-
query
.
Result
{
Error
:
errors
.
New
(
"walk failed: "
+
err
.
Error
())}
// Replicates the logic in ResultsWithChan but actually respects calls
// to `Close`.
b
:=
query
.
NewResultBuilder
(
q
)
b
.
Process
.
Go
(
func
(
p
goprocess
.
Process
)
{
err
:=
fs
.
walkTopLevel
(
fs
.
path
,
b
)
if
err
==
nil
{
return
}
}()
return
query
.
ResultsWithChan
(
q
,
reschan
),
nil
select
{
case
b
.
Output
<-
query
.
Result
{
Error
:
errors
.
New
(
"walk failed: "
+
err
.
Error
())}
:
case
<-
p
.
Closing
()
:
}
})
go
b
.
Process
.
CloseAfterChildren
()
return
b
.
Results
(),
nil
}
func
(
fs
*
Datastore
)
walkTopLevel
(
path
string
,
res
chan
chan
query
.
Result
)
error
{
func
(
fs
*
Datastore
)
walkTopLevel
(
path
string
,
res
ult
*
query
.
Result
Builder
)
error
{
dir
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
return
err
...
...
@@ -653,16 +661,21 @@ func (fs *Datastore) walkTopLevel(path string, reschan chan query.Result) error
return
err
}
for
_
,
dir
:=
range
names
{
if
len
(
dir
)
==
0
||
dir
[
0
]
==
'.'
{
continue
}
err
=
fs
.
walk
(
filepath
.
Join
(
path
,
dir
),
res
chan
)
err
=
fs
.
walk
(
filepath
.
Join
(
path
,
dir
),
res
ult
)
if
err
!=
nil
{
return
err
}
// Are we closing?
select
{
case
<-
result
.
Process
.
Closing
()
:
return
nil
default
:
}
}
return
nil
}
...
...
@@ -957,7 +970,7 @@ func (fs *Datastore) Accuracy() string {
return
string
(
fs
.
storedValue
.
Accuracy
)
}
func
(
fs
*
Datastore
)
walk
(
path
string
,
res
chan
chan
query
.
Result
)
error
{
func
(
fs
*
Datastore
)
walk
(
path
string
,
res
ult
*
query
.
Result
Builder
)
error
{
dir
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
if
os
.
IsNotExist
(
err
)
{
...
...
@@ -993,10 +1006,14 @@ func (fs *Datastore) walk(path string, reschan chan query.Result) error {
continue
}
reschan
<-
query
.
Result
{
select
{
case
result
.
Output
<-
query
.
Result
{
Entry
:
query
.
Entry
{
Key
:
key
.
String
(),
},
}
:
case
<-
result
.
Process
.
Closing
()
:
return
nil
}
}
return
nil
...
...
flatfs_test.go
View file @
dc81160a
...
...
@@ -988,3 +988,34 @@ func BenchmarkBatchedPut(b *testing.B) {
}
b
.
StopTimer
()
// avoid counting cleanup
}
func
TestQueryLeak
(
t
*
testing
.
T
)
{
temp
,
cleanup
:=
tempdir
(
t
)
defer
cleanup
()
fs
,
err
:=
flatfs
.
CreateOrOpen
(
temp
,
flatfs
.
Prefix
(
2
),
false
)
if
err
!=
nil
{
t
.
Fatalf
(
"New fail: %v
\n
"
,
err
)
}
defer
fs
.
Close
()
for
i
:=
0
;
i
<
1000
;
i
++
{
err
=
fs
.
Put
(
datastore
.
NewKey
(
fmt
.
Sprint
(
i
)),
[]
byte
(
"foobar"
))
if
err
!=
nil
{
t
.
Fatalf
(
"Put fail: %v
\n
"
,
err
)
}
}
before
:=
runtime
.
NumGoroutine
()
for
i
:=
0
;
i
<
200
;
i
++
{
res
,
err
:=
fs
.
Query
(
query
.
Query
{
KeysOnly
:
true
})
if
err
!=
nil
{
t
.
Errorf
(
"Query fail: %v
\n
"
,
err
)
}
res
.
Close
()
}
after
:=
runtime
.
NumGoroutine
()
if
after
-
before
>
100
{
t
.
Errorf
(
"leaked %d goroutines"
,
after
-
before
)
}
}
package.json
View file @
dc81160a
...
...
@@ -17,6 +17,12 @@
"hash"
:
"QmaRb5yNXKonhbkpNxNawoydk4N6es6b4fPj19sjEKsh5D"
,
"name"
:
"go-datastore"
,
"version"
:
"3.4.0"
},
{
"author"
:
"whyrusleeping"
,
"hash"
:
"QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP"
,
"name"
:
"goprocess"
,
"version"
:
"1.0.0"
}
],
"gxVersion"
:
"0.8.0"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment