Skip to content

Commit a8bd506

Browse files
committed
core: add Parser.Close() to fix memory leak (#216)
Parser.Close() will call msgDispatcher.RemoveAllQueues() to terminate the goroutine handling net-messages. It needs to be called by the user before discarding the Parser.
1 parent 387af9a commit a8bd506

File tree

12 files changed

+48
-0
lines changed

12 files changed

+48
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func main() {
7676
defer f.Close()
7777

7878
p := dem.NewParser(f)
79+
defer p.Close()
7980

8081
// Register handler on kill events
8182
p.RegisterEventHandler(func(e events.Kill) {

examples/entities/entities.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func main() {
1818
defer f.Close()
1919

2020
p := demoinfocs.NewParser(f)
21+
defer p.Close()
2122

2223
p.RegisterEventHandler(func(events.DataTablesParsed) {
2324
p.ServerClasses().FindByName("CWeaponAWP").OnEntityCreated(func(ent st.Entity) {

examples/heatmap/heatmap.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func main() {
3434
defer f.Close()
3535

3636
p := demoinfocs.NewParser(f)
37+
defer p.Close()
3738

3839
// Parse header (contains map-name etc.)
3940
header, err := p.ParseHeader()

examples/nade-trajectories/nade_trajectories.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ func main() {
4646
defer f.Close()
4747

4848
p := demoinfocs.NewParser(f)
49+
defer p.Close()
4950

5051
header, err := p.ParseHeader()
5152
checkError(err)

examples/net-messages/netmessages.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func main() {
2626
}
2727

2828
p := demoinfocs.NewParserWithConfig(f, cfg)
29+
defer p.Close()
2930

3031
// Register handler for BSPDecal messages
3132
p.RegisterNetMessageHandler(func(m *msg.CSVCMsg_BSPDecal) {

examples/print-events/print_events.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func main() {
1818
defer f.Close()
1919

2020
p := demoinfocs.NewParser(f)
21+
defer p.Close()
2122

2223
// Parse header
2324
header, err := p.ParseHeader()

pkg/demoinfocs/examples_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func ExampleParser() {
2222
defer f.Close()
2323

2424
p := demoinfocs.NewParser(f)
25+
defer p.Close()
2526

2627
// Register handler on kill events
2728
p.RegisterEventHandler(func(e events.Kill) {

pkg/demoinfocs/fake/parser.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,3 +226,9 @@ func max(numbers map[int][]interface{}) (maxNumber int) {
226226
func (p *Parser) Cancel() {
227227
p.Called()
228228
}
229+
230+
// Close is a mock-implementation of Parser.Close().
231+
// NOP implementation.
232+
func (p *Parser) Close() {
233+
p.Called()
234+
}

pkg/demoinfocs/parser.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Example (without error handling):
3333
3434
f, _ := os.Open("/path/to/demo.dem")
3535
p := dem.NewParser(f)
36+
defer p.Close()
3637
header := p.ParseHeader()
3738
fmt.Println("Map:", header.MapName)
3839
p.RegisterEventHandler(func(e events.BombExplode) {
@@ -235,6 +236,12 @@ func (p *parser) UnregisterNetMessageHandler(identifier dp.HandlerIdentifier) {
235236
p.msgDispatcher.UnregisterHandler(identifier)
236237
}
237238

239+
// Close closes any open resources used by the Parser (go routines, file handles).
240+
// This must be called before discarding the Parser to avoid memory leaks.
241+
func (p *parser) Close() {
242+
p.msgDispatcher.RemoveAllQueues()
243+
}
244+
238245
func (p *parser) error() error {
239246
p.errLock.Lock()
240247
err := p.err

pkg/demoinfocs/parser_interface.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
//
2525
// f, _ := os.Open("/path/to/demo.dem")
2626
// p := dem.NewParser(f)
27+
// defer p.Close()
2728
// header := p.ParseHeader()
2829
// fmt.Println("Map:", header.MapName)
2930
// p.RegisterEventHandler(func(e events.BombExplode) {
@@ -98,6 +99,9 @@ type Parser interface {
9899
//
99100
// The identifier is returned at registration by RegisterNetMessageHandler().
100101
UnregisterNetMessageHandler(identifier dp.HandlerIdentifier)
102+
// Close closes any open resources used by the Parser (go routines, file handles).
103+
// This must be called before discarding the Parser to avoid memory leaks.
104+
Close()
101105
// ParseHeader attempts to parse the header of the demo and returns it.
102106
// If not done manually this will be called by Parser.ParseNextFrame() or Parser.ParseToEnd().
103107
//

0 commit comments

Comments
 (0)