Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data race when closing listener #357

Open
alarmfox opened this issue Sep 16, 2021 · 2 comments
Open

Data race when closing listener #357

alarmfox opened this issue Sep 16, 2021 · 2 comments

Comments

@alarmfox
Copy link

Hello, I'm using this library and i get data race when i run the following program with the command:

go run -race main.go

func main() {
	exitCh := make(chan os.Signal, 1)
	signal.Notify(exitCh, os.Interrupt, syscall.SIGTERM)
	defer close(exitCh)

	wg := sync.WaitGroup{}
	// start listening
	listener := gosnmp.NewTrapListener()
	wg.Add(1)
	go func() {
		defer wg.Done()

		listener.Listen("0.0.0.0:2162")
	}()

	<-exitCh
	listener.Close()
	wg.Wait()
}

This is the output:

==================
WARNING: DATA RACE
Read at 0x00c000186018 by main goroutine:
  github.com/gosnmp/gosnmp.(*TrapListener).Close()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:164 +0x5a
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:28 +0x370

Previous write at 0x00c000186018 by goroutine 9:
  github.com/gosnmp/gosnmp.(*TrapListener).listenUDP()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:181 +0xdc
  github.com/gosnmp/gosnmp.(*TrapListener).Listen()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:348 +0x4f4
  main.main.func1()
      /home/giuseppe/dev/gosnmp-test/main.go:24 +0x9e

Goroutine 9 (running) created at:
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:21 +0x35a
==================
==================
WARNING: DATA RACE
Read at 0x00c0000a2018 by main goroutine:
  net.(*conn).ok()
      /usr/local/go/src/net/net.go:174 +0x89
  net.(*conn).LocalAddr()
      /usr/local/go/src/net/net.go:218 +0x93
  github.com/gosnmp/gosnmp.(*TrapListener).Close()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:167 +0x6b
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:28 +0x370

Previous write at 0x00c0000a2018 by goroutine 9:
  net.newUDPConn()
      /usr/local/go/src/net/udpsock.go:198 +0x114
  net.(*sysListener).listenUDP()
      /usr/local/go/src/net/udpsock_posix.go:113 +0x145
  net.ListenUDP()
      /usr/local/go/src/net/udpsock.go:243 +0x199
  github.com/gosnmp/gosnmp.(*TrapListener).listenUDP()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:181 +0xab
  github.com/gosnmp/gosnmp.(*TrapListener).Listen()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:348 +0x4f4
  main.main.func1()
      /home/giuseppe/dev/gosnmp-test/main.go:24 +0x9e

Goroutine 9 (running) created at:
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:21 +0x35a
==================
==================
WARNING: DATA RACE
Read at 0x00c0000d4060 by main goroutine:
  net.(*conn).LocalAddr()
      /usr/local/go/src/net/net.go:221 +0xbc
  github.com/gosnmp/gosnmp.(*TrapListener).Close()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:167 +0x6b
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:28 +0x370

Previous write at 0x00c0000d4060 by goroutine 9:
  net.newFD()
      /usr/local/go/src/net/fd_unix.go:28 +0x104
  net.socket()
      /usr/local/go/src/net/sock_posix.go:28 +0xc9
  net.internetSocket()
      /usr/local/go/src/net/ipsock_posix.go:142 +0x12f
  net.(*sysListener).listenUDP()
      /usr/local/go/src/net/udpsock_posix.go:109 +0xf1
  net.ListenUDP()
      /usr/local/go/src/net/udpsock.go:243 +0x199
  github.com/gosnmp/gosnmp.(*TrapListener).listenUDP()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:181 +0xab
  github.com/gosnmp/gosnmp.(*TrapListener).Listen()
      /home/giuseppe/go/pkg/mod/github.com/gosnmp/[email protected]/trap.go:348 +0x4f4
  main.main.func1()
      /home/giuseppe/dev/gosnmp-test/main.go:24 +0x9e

Goroutine 9 (running) created at:
  main.main()
      /home/giuseppe/dev/gosnmp-test/main.go:21 +0x35a
==================
Found 3 data race(s)
exit status 66

Anyone had the same issue? Am i doing something wrong?

@sedyh
Copy link

sedyh commented Aug 1, 2022

It looks like the internal listener doesn't release the connection during the entire lifetime. Looks like a bug.
Right now, you can set the finish field manually, which will lead to a normal closing of the connection.

func closeTrapListener(f *g.TrapListener) {
	pointerVal := reflect.ValueOf(f)
	val := reflect.Indirect(pointerVal)
	member := val.FieldByName("finish")
	if !member.IsValid() {
		return
	}
	ptrToY := unsafe.Pointer(member.UnsafeAddr())
	realPtrToY := (*int32)(ptrToY)
	atomic.StoreInt32(realPtrToY, 1)
}

Full example:

package main

import (
	"fmt"
	"log"
	"reflect"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/gosnmp/gosnmp"
)

func main() {
	listener := gosnmp.NewTrapListener()
	go func() {
		fmt.Println("started")
		if err := listener.Listen("0.0.0.0:2162"); err != nil {
			log.Fatal(err)
		}
	}()
	<-time.After(1 * time.Second)

	fmt.Println("closed")
	closeTrapListener(listener)
	<-time.After(1 * time.Second)
}

func closeTrapListener(f *g.TrapListener) {
	pointerVal := reflect.ValueOf(f)
	val := reflect.Indirect(pointerVal)
	member := val.FieldByName("finish")
	if !member.IsValid() {
		return
	}
	ptrToY := unsafe.Pointer(member.UnsafeAddr())
	realPtrToY := (*int32)(ptrToY)
	atomic.StoreInt32(realPtrToY, 1)
}
go run -race .
started
closed

@alarmfox
Copy link
Author

Thank you for the response, i was writing a more diligent way to handle connection with context.Context support and i got this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants