Description

When listen to unix socket, socket file are not removed when stopping gin process (use Ctrl + C). The next time it is executed, the process will report an error: [GIN-debug] [ERROR] listen unix /tmp/testgin.sock: bind: address already in use

How to reproduce

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "pong",
        })
    })
    file := "/tmp/testgin.sock"
    //os.Remove(file)
    r.RunUnix(file)
}

Environment

  • go version: v1.20.3
  • gin version (or commit ref): v1.9.1
  • operating system: osx, ubuntu

Comment From: ismdeep

2280

Comment From: howcrazy

The socket should instead be cleaned up at shutdown.

It creates the sock file but does not delete it after Ctrl + C or stop by supervisord. defer os.Remove(file) not executed.

Maybe I should handle this situation manually?

Comment From: openarun

+1

Comment From: daftaupe

The socket should instead be cleaned up at shutdown.

It creates the sock file but does not delete it after Ctrl + C or stop by supervisord. defer os.Remove(file) not executed.

Maybe I should handle this situation manually?

I don't think you should have to, if the service is not running anymore, the socket should disappear imo.

Comment From: howcrazy

The socket should instead be cleaned up at shutdown.

It creates the sock file but does not delete it after Ctrl + C or stop by supervisord. defer os.Remove(file) not executed. Maybe I should handle this situation manually?

I don't think you should have to, if the service is not running anymore, the socket should disappear imo.

But it still there 😂

Comment From: XANi

I looked into it a bit and it's some really weird problem.

For context, simple unix socket

func main() {
    l, err := net.Listen("unix", "sock")
    fmt.Println(err)
    defer   l.Close()
}

will get removed without any extra cleanup but the moment builtin Go stuff in involved, socket gets stale:

package main

import (
    "fmt"
    "net"
    "net/http"
)

type H struct{}

func (h *H) ServeHTTP(w http.ResponseWriter, r *http.Request) {

}

func main() {
    u, err := net.Listen("unix", "sock")
    fmt.Println(err)
    if err == nil {
        defer u.Close()
        fmt.Println("press C-c and run me again")
        fmt.Println(http.Serve(u, &H{}))
    }

}

TL;DR nothing Gin can really do here. https://github.com/golang/go/issues/70985