mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-25 23:01:38 +00:00
Merge pull request #255 from Arceliar/tunfix
Fix panic when writing to closed tun (from race during shutdown)
This commit is contained in:
commit
575572d9a0
@ -5,6 +5,7 @@ package yggdrasil
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/songgao/packets/ethernet"
|
"github.com/songgao/packets/ethernet"
|
||||||
@ -24,6 +25,8 @@ type tunAdapter struct {
|
|||||||
icmpv6 icmpv6
|
icmpv6 icmpv6
|
||||||
mtu int
|
mtu int
|
||||||
iface *water.Interface
|
iface *water.Interface
|
||||||
|
mutex sync.RWMutex // Protects the below
|
||||||
|
isOpen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the maximum supported MTU for the platform based on the defaults in
|
// Gets the maximum supported MTU for the platform based on the defaults in
|
||||||
@ -50,8 +53,11 @@ func (tun *tunAdapter) start(ifname string, iftapmode bool, addr string, mtu int
|
|||||||
if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
|
if err := tun.setup(ifname, iftapmode, addr, mtu); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() { panic(tun.read()) }()
|
tun.mutex.Lock()
|
||||||
go func() { panic(tun.write()) }()
|
tun.isOpen = true
|
||||||
|
tun.mutex.Unlock()
|
||||||
|
go func() { tun.core.log.Println("WARNING: tun.read() exited with error:", tun.read()) }()
|
||||||
|
go func() { tun.core.log.Println("WARNING: tun.write() exited with error:", tun.write()) }()
|
||||||
if iftapmode {
|
if iftapmode {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -148,12 +154,26 @@ func (tun *tunAdapter) write() error {
|
|||||||
len(data)) // Payload length
|
len(data)) // Payload length
|
||||||
copy(frame[tun_ETHER_HEADER_LENGTH:], data[:])
|
copy(frame[tun_ETHER_HEADER_LENGTH:], data[:])
|
||||||
if _, err := tun.iface.Write(frame); err != nil {
|
if _, err := tun.iface.Write(frame); err != nil {
|
||||||
panic(err)
|
tun.mutex.RLock()
|
||||||
|
open := tun.isOpen
|
||||||
|
tun.mutex.RUnlock()
|
||||||
|
if !open {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if _, err := tun.iface.Write(data); err != nil {
|
if _, err := tun.iface.Write(data); err != nil {
|
||||||
panic(err)
|
tun.mutex.RLock()
|
||||||
|
open := tun.isOpen
|
||||||
|
tun.mutex.RUnlock()
|
||||||
|
if !open {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
util.PutBytes(data)
|
util.PutBytes(data)
|
||||||
@ -173,8 +193,15 @@ func (tun *tunAdapter) read() error {
|
|||||||
for {
|
for {
|
||||||
n, err := tun.iface.Read(buf)
|
n, err := tun.iface.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// panic(err)
|
tun.mutex.RLock()
|
||||||
return err
|
open := tun.isOpen
|
||||||
|
tun.mutex.RUnlock()
|
||||||
|
if !open {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// panic(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
o := 0
|
o := 0
|
||||||
if tun.iface.IsTAP() {
|
if tun.iface.IsTAP() {
|
||||||
@ -202,6 +229,9 @@ func (tun *tunAdapter) read() error {
|
|||||||
// process stops. Typically this operation will happen quickly, but on macOS
|
// process stops. Typically this operation will happen quickly, but on macOS
|
||||||
// it can block until a read operation is completed.
|
// it can block until a read operation is completed.
|
||||||
func (tun *tunAdapter) close() error {
|
func (tun *tunAdapter) close() error {
|
||||||
|
tun.mutex.Lock()
|
||||||
|
tun.isOpen = false
|
||||||
|
tun.mutex.Unlock()
|
||||||
if tun.iface == nil {
|
if tun.iface == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user