On Fri, Feb 9, 2024 at 11:57 AM Kurtis Rader <kra...@skepticism.us> wrote:
>
> 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.

That is true, but the Go standard library's net package does use
non-blocking calls to connect internally when implementing net.Dial
and friends.

I don't have any problem running the original program on Linux 6.5.13.

Ian


> 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.
>
>
>
> --
> 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.

-- 
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/CAOyqgcVWPysC2vsqvXeVWmwswNBEQ5uaKQkPsZLguuiDnY_Omw%40mail.gmail.com.

Reply via email to