Close hack listener before closing channel

This commit is contained in:
Jason A. Donenfeld 2018-05-21 03:31:44 +02:00
parent e28d70f5b2
commit 6307bfcdf4

View File

@ -22,6 +22,7 @@ import (
"net" "net"
"os" "os"
"strconv" "strconv"
"sync"
"time" "time"
"unsafe" "unsafe"
) )
@ -32,16 +33,16 @@ const (
) )
type NativeTun struct { type NativeTun struct {
fd *os.File fd *os.File
fdCancel *rwcancel.RWCancel fdCancel *rwcancel.RWCancel
index int32 // if index index int32 // if index
name string // name of interface name string // name of interface
errors chan error // async error handling errors chan error // async error handling
events chan TUNEvent // device related events events chan TUNEvent // device related events
nopi bool // the device was pased IFF_NO_PI nopi bool // the device was pased IFF_NO_PI
netlinkSock int netlinkSock int
netlinkCancel *rwcancel.RWCancel netlinkCancel *rwcancel.RWCancel
hackListenerClosed sync.Mutex
statusListenersShutdown chan struct{} statusListenersShutdown chan struct{}
} }
@ -50,6 +51,7 @@ func (tun *NativeTun) File() *os.File {
} }
func (tun *NativeTun) RoutineHackListener() { func (tun *NativeTun) RoutineHackListener() {
defer tun.hackListenerClosed.Unlock()
/* This is needed for the detection to work across network namespaces /* This is needed for the detection to work across network namespaces
* If you are reading this and know a better method, please get in touch. * If you are reading this and know a better method, please get in touch.
*/ */
@ -91,6 +93,7 @@ func createNetlinkSocket() (int, error) {
func (tun *NativeTun) RoutineNetlinkListener() { func (tun *NativeTun) RoutineNetlinkListener() {
defer func() { defer func() {
unix.Close(tun.netlinkSock) unix.Close(tun.netlinkSock)
tun.hackListenerClosed.Lock()
close(tun.events) close(tun.events)
}() }()
@ -455,6 +458,7 @@ func CreateTUNFromFile(fd *os.File) (TUNDevice, error) {
return nil, err return nil, err
} }
tun.hackListenerClosed.Lock()
go tun.RoutineNetlinkListener() go tun.RoutineNetlinkListener()
go tun.RoutineHackListener() // cross namespace go tun.RoutineHackListener() // cross namespace