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

net: after call of {TCP,UDP,IP,Unix}Conn/{TCP,Unix}Listener.File(), the deadline will be ineffective #21862

Closed
goosman-lei opened this issue Sep 13, 2017 · 6 comments

Comments

Projects
None yet
6 participants
@goosman-lei
Copy link

commented Sep 13, 2017

if err = syscall.SetNonblock(ns, false); err != nil {

in the under demo code:
the first goroutine, listener is not call (*net.TCPListener).File(), it timeout with setDeadline() works fine

the second goroutine, listener call (*net.TCPListener).File(), after that, the timeout don't work

the third goroutine, listener call (*net.TCPListener).File(), but then set it to non-blocking mode, timeout works fine too

package main

import (
    "fmt"
    "net"
    "sync"
    "syscall"
    "time"
)

func main() {
    wg := new(sync.WaitGroup)
    wg.Add(2)

    go func() {
        addr, _ := net.ResolveTCPAddr("tcp", ":2020")
        l, _ := net.ListenTCP("tcp", addr)
        for {
            l.SetDeadline(time.Now().Add(time.Second))
            c, err := l.AcceptTCP()
            if err != nil {
                if nErr, ok := err.(net.Error); ok && nErr.Timeout() {
                    fmt.Printf("server 1 timeout at: %s\n", time.Now())
                    continue
                }   
                fmt.Printf("server 1 error: %s\n", err)
                break
            }   
            fmt.Printf("server 1 accept from: %s %s\n", c.RemoteAddr().String(), time.Now())
        }   
        wg.Done()
    }() 
    go func() {
        addr, _ := net.ResolveTCPAddr("tcp", ":2021")
        l, _ := net.ListenTCP("tcp", addr)
        l.File()
        for {
            l.SetDeadline(time.Now().Add(time.Second))
            c, err := l.AcceptTCP()
            if err != nil {
                if nErr, ok := err.(net.Error); ok && nErr.Timeout() {
                    fmt.Printf("server 2 timeout at: %s\n", time.Now())
                    continue
                }   
                fmt.Printf("server 2 error: %s\n", err)
                break
            }   
            fmt.Printf("server 2 accept from: %s %s\n", c.RemoteAddr().String(), time.Now())
        }   
        wg.Done()
    }() 
    go func() {
        addr, _ := net.ResolveTCPAddr("tcp", ":2022")
        l, _ := net.ListenTCP("tcp", addr)
        f, _ := l.File()
        syscall.SetNonblock(int(f.Fd()), true)
        for {
            l.SetDeadline(time.Now().Add(time.Second))
            c, err := l.AcceptTCP()
            if err != nil {
                if nErr, ok := err.(net.Error); ok && nErr.Timeout() {
                    fmt.Printf("server 3 timeout at: %s\n", time.Now())
                    continue
                }   
                fmt.Printf("server 3 error: %s\n", err)
                break
            }   
            fmt.Printf("server 3 accept from: %s %s\n", c.RemoteAddr().String(), time.Now())
        }   
        wg.Done()
    }() 

    wg.Wait()
}

@ianlancetaylor ianlancetaylor changed the title After call of (*net.TCPListener).File(), the listener's deadline will ineffective net: after call of (*net.TCPListener).File(), the listener's deadline will ineffective Sep 13, 2017

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Sep 13, 2017

I assume you are running on a Unix system.

I don't see any way to fix this. Do you have any suggestions?

@goosman-lei

This comment has been minimized.

Copy link
Author

commented Sep 19, 2017

I don't understand why here set fd to blocking mode. .
In my opinion, whether set into blocking mode, should taken the control to user programmer

@bradfitz

This comment has been minimized.

Copy link
Member

commented Nov 28, 2017

Is this fixed by (*TCPListener) SyscallConn() (syscall.RawConn, error) in Go 1.10?

https://tip.golang.org/pkg/net/#TCPListener.SyscallConn

@crvv

This comment has been minimized.

Copy link
Contributor

commented Nov 30, 2017

Is this fixed by (*TCPListener) SyscallConn() (syscall.RawConn, error) in Go 1.10?

The issue is the method *(net.TCPListener).File makes the deadline ineffective.
It can't be fixed by adding a new method. The method File() can still break the deadline.

SyscallConn can give me the fd without making the deadline ineffective.
So I think it's good enough if the behavior is documented clearly.

package main

import (
        "fmt"
        "net"
        "time"
)

func main() {
        addr, _ := net.ResolveTCPAddr("tcp", ":2022")
        l, _ := net.ListenTCP("tcp", addr)
        sc, _ := l.SyscallConn()
        sc.Control(func(fd uintptr) { println(fd) })
        for {
                l.SetDeadline(time.Now().Add(time.Second))
                c, err := l.AcceptTCP()
                if err != nil {
                        if nErr, ok := err.(net.Error); ok && nErr.Timeout() {
                                fmt.Printf("server 3 timeout at: %s\n", time.Now())
                                continue
                        }
                        fmt.Printf("server 3 error: %s\n", err)
                        break
                }
                fmt.Printf("server 3 accept from: %s %s\n", c.RemoteAddr().String(), time.Now())
        }
}

@mikioh mikioh changed the title net: after call of (*net.TCPListener).File(), the listener's deadline will ineffective net: after call of {TCP,UDP,IP,Unix}Conn/{TCP,Unix}Listener.File(), the deadline will be ineffective Nov 30, 2017

@gopherbot

This comment has been minimized.

Copy link

commented Dec 8, 2017

Change https://golang.org/cl/82915 mentions this issue: net: calling File disables the SetDeadline methods

@gopherbot gopherbot closed this in a941028 Dec 8, 2017

@mikioh

This comment has been minimized.

Copy link
Contributor

commented Apr 20, 2018

Also see #24942.

@mikioh mikioh removed the WaitingForInfo label Apr 20, 2018

@golang golang locked and limited conversation to collaborators Apr 20, 2019

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.