mirror of
				https://github.com/yggdrasil-network/yggdrasil-go.git
				synced 2025-11-04 03:05:07 +03:00 
			
		
		
		
	Try to fix TUN/TAP conn reader leakage
This commit is contained in:
		
							parent
							
								
									7edcab8621
								
							
						
					
					
						commit
						d34600b5f9
					
				
					 1 changed files with 27 additions and 12 deletions
				
			
		| 
						 | 
					@ -11,6 +11,8 @@ import (
 | 
				
			||||||
	"golang.org/x/net/ipv6"
 | 
						"golang.org/x/net/ipv6"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const tunConnTimeout = 2 * time.Minute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type tunConn struct {
 | 
					type tunConn struct {
 | 
				
			||||||
	tun   *TunAdapter
 | 
						tun   *TunAdapter
 | 
				
			||||||
	conn  *yggdrasil.Conn
 | 
						conn  *yggdrasil.Conn
 | 
				
			||||||
| 
						 | 
					@ -49,24 +51,37 @@ func (s *tunConn) reader() error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						s.tun.log.Debugln("Starting conn reader for", s)
 | 
				
			||||||
	var n int
 | 
						var n int
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	read := make(chan bool)
 | 
						read := make(chan bool)
 | 
				
			||||||
	b := make([]byte, 65535)
 | 
						b := make([]byte, 65535)
 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
			// TODO don't start a new goroutine for every packet read, this is probably a big part of the slowdowns we saw when refactoring
 | 
							s.tun.log.Debugln("Starting conn reader helper for", s)
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								s.conn.SetReadDeadline(time.Now().Add(tunConnTimeout))
 | 
				
			||||||
			if n, err = s.conn.Read(b); err != nil {
 | 
								if n, err = s.conn.Read(b); err != nil {
 | 
				
			||||||
				s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn read error:", err)
 | 
									s.tun.log.Errorln(s.conn.String(), "TUN/TAP conn read error:", err)
 | 
				
			||||||
				if e, eok := err.(yggdrasil.ConnError); eok && !e.Temporary() {
 | 
									if e, eok := err.(yggdrasil.ConnError); eok {
 | 
				
			||||||
					close(s.stop)
 | 
										switch {
 | 
				
			||||||
				} else {
 | 
										case e.Temporary():
 | 
				
			||||||
						read <- false
 | 
											read <- false
 | 
				
			||||||
				}
 | 
											continue
 | 
				
			||||||
 | 
										case e.Timeout():
 | 
				
			||||||
 | 
											s.tun.log.Debugln("Conn reader for helper", s, "timed out")
 | 
				
			||||||
 | 
											fallthrough
 | 
				
			||||||
 | 
										default:
 | 
				
			||||||
 | 
											s.tun.log.Debugln("Stopping conn reader helper for", s)
 | 
				
			||||||
 | 
											s.close()
 | 
				
			||||||
						return
 | 
											return
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									read <- false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			read <- true
 | 
								read <- true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case r := <-read:
 | 
							case r := <-read:
 | 
				
			||||||
			if r && n > 0 {
 | 
								if r && n > 0 {
 | 
				
			||||||
| 
						 | 
					@ -93,6 +108,7 @@ func (s *tunConn) writer() error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						s.tun.log.Debugln("Starting conn writer for", s)
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-s.stop:
 | 
							case <-s.stop:
 | 
				
			||||||
| 
						 | 
					@ -134,8 +150,7 @@ func (s *tunConn) stillAlive() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *tunConn) checkForTimeouts() error {
 | 
					func (s *tunConn) checkForTimeouts() error {
 | 
				
			||||||
	const timeout = 2 * time.Minute
 | 
						timer := time.NewTimer(tunConnTimeout)
 | 
				
			||||||
	timer := time.NewTimer(timeout)
 | 
					 | 
				
			||||||
	defer util.TimerStop(timer)
 | 
						defer util.TimerStop(timer)
 | 
				
			||||||
	defer s.close()
 | 
						defer s.close()
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
| 
						 | 
					@ -145,7 +160,7 @@ func (s *tunConn) checkForTimeouts() error {
 | 
				
			||||||
				return errors.New("connection closed")
 | 
									return errors.New("connection closed")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			util.TimerStop(timer)
 | 
								util.TimerStop(timer)
 | 
				
			||||||
			timer.Reset(timeout)
 | 
								timer.Reset(tunConnTimeout)
 | 
				
			||||||
		case <-timer.C:
 | 
							case <-timer.C:
 | 
				
			||||||
			return errors.New("timed out")
 | 
								return errors.New("timed out")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue