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.

Reply via email to