Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit eb46904

Browse files
committed
Replace SetFinalizer with AddCleanup for Go 1.24+
Switch to runtime.AddCleanup for more reliable resource cleanup. This provides better finalization behavior compared to SetFinalizer. Uses atomic operations to prevent race conditions during cleanup.
1 parent 476083a commit eb46904

File tree

4 files changed

+31
-14
lines changed

4 files changed

+31
-14
lines changed

‎CHANGELOG.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changes
22

3+
## 2.0.0-beta.10
4+
5+
- Replaced `runtime.SetFinalizer` with `runtime.AddCleanup` for resource
6+
cleanup in Go 1.24+. This provides more reliable finalization behavior and
7+
better garbage collection performance.
8+
39
## 2.0.0-beta.9 - 2025年08月23日
410

511
- **SECURITY**: Fixed integer overflow vulnerability in search tree size

‎reader.go‎

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ import (
112112
"net/netip"
113113
"os"
114114
"runtime"
115+
"sync/atomic"
115116
"time"
116117

117118
"github.com/oschwald/maxminddb-golang/v2/internal/decoder"
@@ -122,6 +123,12 @@ const dataSectionSeparatorSize = 16
122123

123124
var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com")
124125

126+
// mmapCleanup holds the data needed to safely cleanup memory-mapped files.
127+
type mmapCleanup struct {
128+
hasMapped *atomic.Bool
129+
data []byte
130+
}
131+
125132
// Reader holds the data corresponding to the MaxMind DB file. Its only public
126133
// field is Metadata, which contains the metadata from the MaxMind DB file.
127134
//
@@ -134,7 +141,7 @@ type Reader struct {
134141
ipv4Start uint
135142
ipv4StartBitDepth int
136143
nodeOffsetMult uint
137-
hasMappedFile bool
144+
hasMappedFile atomic.Bool
138145
}
139146

140147
// Metadata holds the metadata decoded from the MaxMind DB file.
@@ -252,8 +259,16 @@ func Open(file string, options ...ReaderOption) (*Reader, error) {
252259
return nil, err
253260
}
254261

255-
reader.hasMappedFile = true
256-
runtime.SetFinalizer(reader, (*Reader).Close)
262+
reader.hasMappedFile.Store(true)
263+
cleanup := &mmapCleanup{
264+
data: data,
265+
hasMapped: &reader.hasMappedFile,
266+
}
267+
runtime.AddCleanup(reader, func(mc *mmapCleanup) {
268+
if mc.hasMapped.CompareAndSwap(true, false) {
269+
_ = munmap(mc.data)
270+
}
271+
}, cleanup)
257272
return reader, nil
258273
}
259274

@@ -281,9 +296,7 @@ func openFallback(f *os.File, size int) (data []byte, err error) {
281296
// Close returns the resources used by the database to the system.
282297
func (r *Reader) Close() error {
283298
var err error
284-
if r.hasMappedFile {
285-
runtime.SetFinalizer(r, nil)
286-
r.hasMappedFile = false
299+
if r.hasMappedFile.CompareAndSwap(true, false) {
287300
err = munmap(r.buffer)
288301
}
289302
r.buffer = nil
@@ -384,7 +397,7 @@ func (r *Reader) Lookup(ip netip.Addr) Result {
384397
}
385398
offset, err := r.resolveDataPointer(pointer)
386399
return Result{
387-
decoder: r.decoder,
400+
reader: r,
388401
ip: ip,
389402
offset: uint(offset),
390403
prefixLen: uint8(prefixLen),
@@ -399,7 +412,7 @@ func (r *Reader) LookupOffset(offset uintptr) Result {
399412
return Result{err: errors.New("cannot call LookupOffset on a closed database")}
400413
}
401414

402-
return Result{decoder: r.decoder, offset: uint(offset)}
415+
return Result{reader: r, offset: uint(offset)}
403416
}
404417

405418
func (r *Reader) setIPv4Start() error {

‎result.go‎

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package maxminddb
33
import (
44
"math"
55
"net/netip"
6-
7-
"github.com/oschwald/maxminddb-golang/v2/internal/decoder"
86
)
97

108
const notFound uint = math.MaxUint
@@ -13,7 +11,7 @@ const notFound uint = math.MaxUint
1311
type Result struct {
1412
ip netip.Addr
1513
err error
16-
decoder decoder.ReflectionDecoder
14+
reader *Reader
1715
offset uint
1816
prefixLen uint8
1917
}
@@ -37,7 +35,7 @@ func (r Result) Decode(v any) error {
3735
return nil
3836
}
3937

40-
return r.decoder.Decode(r.offset, v)
38+
return r.reader.decoder.Decode(r.offset, v)
4139
}
4240

4341
// DecodePath unmarshals a value from data section into v, following the
@@ -94,7 +92,7 @@ func (r Result) DecodePath(v any, path ...any) error {
9492
if r.offset == notFound {
9593
return nil
9694
}
97-
return r.decoder.DecodePath(r.offset, path, v)
95+
return r.reader.decoder.DecodePath(r.offset, path, v)
9896
}
9997

10098
// Err provides a way to check whether there was an error during the lookup

‎traverse.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (r *Reader) NetworksWithin(prefix netip.Prefix, options ...NetworksOption)
192192
}
193193

194194
ok := yield(Result{
195-
decoder: r.decoder,
195+
reader: r,
196196
ip: mappedIP(node.ip),
197197
offset: uint(offset),
198198
prefixLen: uint8(node.bit),

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /