Skip to content

Commit f1a3952

Browse files
committed
git: close blob objects when finished
When we read a tree, commit, or tag from gitobj, the object is automatically closed for us, since these objects are relatively small and can be read and parsed all in memory. However, blob objects may be large, so we return a reader which can be used to read the data from the object. In order to properly clean up after ourselves, including closing any object files which may open, we need to call Close on the blob after reading it. Otherwise, we'll eventually run out of file descriptors, causing us to silently hang. Restore the reset function that was removed in e3fcde7 ("git: replace object scanner with one based on gitobj", 2018-09-05) and ensure we close objects and reset the object scanner between every call to Scan.
1 parent 468dc60 commit f1a3952

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

git/object_scanner.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ type object struct {
2020
Size int64
2121
// Type is the type of the object being held.
2222
Type string
23+
// object is the gitobj object being handled.
24+
object gitobj.Object
2325
}
2426

2527
// ObjectScanner is a scanner type that scans for Git objects reference-able in
@@ -68,6 +70,11 @@ func NewObjectScannerFrom(db *gitobj.ObjectDatabase) *ObjectScanner {
6870
// Scan() returns whether the scan was successful, or in other words, whether or
6971
// not the scanner can continue to progress.
7072
func (s *ObjectScanner) Scan(oid string) bool {
73+
if err := s.reset(); err != nil {
74+
s.err = err
75+
return false
76+
}
77+
7178
obj, err := s.scan(oid)
7279
s.object = obj
7380

@@ -88,6 +95,8 @@ func (s *ObjectScanner) Close() error {
8895
return nil
8996
}
9097

98+
s.reset()
99+
91100
return nil
92101
}
93102

@@ -116,6 +125,21 @@ func (s *ObjectScanner) Type() string {
116125
// operation.
117126
func (s *ObjectScanner) Err() error { return s.err }
118127

128+
func (s *ObjectScanner) reset() error {
129+
if s.object != nil {
130+
if c, ok := s.object.object.(interface {
131+
Close() error
132+
}); ok && c != nil {
133+
if err := c.Close(); err != nil {
134+
return err
135+
}
136+
}
137+
}
138+
139+
s.object, s.err = nil, nil
140+
return nil
141+
}
142+
119143
type missingErr struct {
120144
oid string
121145
}
@@ -162,5 +186,6 @@ func (s *ObjectScanner) scan(oid string) (*object, error) {
162186
Oid: oid,
163187
Size: size,
164188
Type: obj.Type().String(),
189+
object: obj,
165190
}, nil
166191
}

0 commit comments

Comments
 (0)