Skip to content

Instantly share code, notes, and snippets.

@yookoala
Last active March 28, 2024 05:43
Show Gist options
  • Save yookoala/39b520931daa08ddd7d2db3c610cc10d to your computer and use it in GitHub Desktop.
Save yookoala/39b520931daa08ddd7d2db3c610cc10d to your computer and use it in GitHub Desktop.
Testing concurrent write to golang net.Conn on unix socket

Concurrent Writing of net.Conn over socket

These files are for testing golang's concurrent writing to the same connection (net.Conn), specifically through a unix socket. To see if concurrent use of net.Conn would lead to contemination of data beting sent.

Method

The file client.go will is program to send multiple data stream of repeated characters to the unix socket "./echo.sock". The number of streams is declared by the arguments of the client.go call. For example:

go run client.go a b c

This will create 3 concurrent goroutines that would write to the same net.Conn without any protection. Each goroutine will continuously sending different repeated characters ("a", "b" or "c"), repeated 3000 times per write, with an open and close blackets around them.

The server a simple logger to log all bytes written:

2024/03/28 11:08:08 received: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
2024/03/28 11:08:08 received: ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc)(bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
2024/03/28 11:08:08 received: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

Result

As shown in logs (running in go-1.21.6), the "a", "b" and "c" characters are not mixing each other. That means that each net.Conn.Write() call on the same net.Conn seems to be atomic and concurrency ready.

Try Yourself

Download the source code. Then run the following 2 commands in 2 separated terminal in the following order:

go run server.go
go run client.go a b c
package main
import (
"log"
"net"
"os"
"strings"
)
func main() {
args := os.Args
n := 3000
strs := args[1:]
never := make(chan struct{})
c, err := net.Dial("unix", "./echo.sock")
if err != nil {
log.Fatal(err)
}
for _, toRepeat := range strs {
// Create goroutines to concurrent write
// to the conn and see if the contents mixed up.
go func(toRepeat string, n int) {
toWrite := "(" + strings.Repeat(toRepeat, n) + ")"
for {
_, err := c.Write([]byte(toWrite))
if err != nil {
log.Fatal(err)
}
}
}(toRepeat, n)
}
<-never
}
package main
import (
"io"
"log"
"net"
"os"
"os/signal"
)
func main() {
l, err := net.Listen("unix", "./echo.sock")
if err != nil {
log.Printf("listen error: %s", err.Error())
return
}
// Correctly close the socket and remove the
// unix socket file when the server is stopped
// by Ctrl+C.
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt)
go func(ch chan os.Signal) {
<-ch
l.Close()
close(ch)
}(ch)
for {
c, err := l.Accept()
if err != nil {
log.Printf("accept error: %s", err.Error())
return
}
go func(c net.Conn) {
defer c.Close()
buf := make([]byte, 1024)
for {
n, err := c.Read(buf)
if err == io.EOF {
return
}
if err != nil {
log.Printf("read error: %s", err.Error())
return
}
log.Printf("received: %s", string(buf[:n]))
}
}(c)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment