The connect() syscall is normally blocking. It doesn't return until the connection is established or an error occurs. It can be made non-blocking by putting the file-descriptor into non-blocking mode before the connect() call. However, that then requires either an async callback or another syscall to check whether the connection was established or an error occurred. Neither approach is idiomatic Go.
On Fri, Feb 9, 2024 at 7:29 AM Venkat T V <venkat...@gmail.com> wrote: > Hi, > > I am debugging an issue where a server opening a large number of > connections on startup sometimes dies with "program exceeds 10000-thread > limit". I know file IO operations could lock up an OS thread. Still seeing > this crash after eliminating file IO, and it looks like "syscall.connect" > is a blocking call and could tie up an OS thread. This is on Linux with > golang 1.21.7. > > I wrote a small program to test this out. Running this with "go run > osthreads.go -parallel 500 -threads 5" does trigger crashes sometimes, and > I see goroutines blocked on "syscall.connect" and "syscall.fcntl". Could I > get confirmation that this is expected behavior and Connect is a blocking > syscall? > > === > package main > > import ( > "flag" > "fmt" > "net" > "runtime" > "runtime/debug" > "sync" > "time" > ) > > func main() { > numThreads := flag.Int("threads", 10, "number of threads (in addition to > GOMAXPROCS)") > parallelism := flag.Int("parallel", 100, "number of parallel goroutines > to start") > flag.Parse() > > maxThreads := runtime.GOMAXPROCS(-1) + *numThreads > fmt.Printf("GOMAXPROCS=%d, max threads=%d\n", runtime.GOMAXPROCS(-1), > maxThreads) > debug.SetMaxThreads(maxThreads) > > // Server that does not accept any connections > listener, err := net.Listen("tcp", "127.0.0.1:9090") > if err != nil { > fmt.Println(err) > return > } > defer listener.Close() > > wg := sync.WaitGroup{} > startSignal := make(chan struct{}) > > // Spawn all goroutines > for i := 0; i < *parallelism; i++ { > wg.Add(1) > go func(id int) { > defer wg.Done() > <-startSignal > > conn, err := net.DialTimeout("tcp", "127.0.0.1:9090", time.Second) > if err != nil { > fmt.Printf("%d: error: %s\n", id, err) > return > } > defer conn.Close() > time.Sleep(time.Second) > }(i) > } > > time.Sleep(time.Second) > > // Start them all at once > close(startSignal) > wg.Wait() > } > > === > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/33ab22bf-088a-4724-8cfb-62b7f51fca96n%40googlegroups.com > <https://groups.google.com/d/msgid/golang-nuts/33ab22bf-088a-4724-8cfb-62b7f51fca96n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- Kurtis Rader Caretaker of the exceptional canines Junior and Hank -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CABx2%3DD92p6ZBjugETbX%3D5KjCqS7HH-Dv4PSuUg%3D9AZwBbioG1A%40mail.gmail.com.