diff --git a/modules/graceful/net_unix.go b/modules/graceful/net_unix.go index 680ff529af..c7524a79db 100644 --- a/modules/graceful/net_unix.go +++ b/modules/graceful/net_unix.go @@ -23,6 +23,7 @@ import ( const ( listenFDs = "LISTEN_FDS" startFD = 3 + unlinkFDs = "GITEA_UNLINK_FDS" ) // In order to keep the working directory the same as when we started we record @@ -33,8 +34,10 @@ var ( once = sync.Once{} mutex = sync.Mutex{} - providedListeners = []net.Listener{} - activeListeners = []net.Listener{} + providedListenersToUnlink = []bool{} + activeListenersToUnlink = []bool{} + providedListeners = []net.Listener{} + activeListeners = []net.Listener{} ) func getProvidedFDs() (savedErr error) { @@ -53,6 +56,16 @@ func getProvidedFDs() (savedErr error) { return } + fdsToUnlinkStr := strings.Split(os.Getenv(unlinkFDs), ",") + providedListenersToUnlink = make([]bool, n) + for _, fdStr := range fdsToUnlinkStr { + i, err := strconv.Atoi(fdStr) + if err != nil || i < 0 || i >= n { + continue + } + providedListenersToUnlink[i] = true + } + for i := startFD; i < n+startFD; i++ { file := os.NewFile(uintptr(i), fmt.Sprintf("listener_FD%d", i)) @@ -136,8 +149,11 @@ func GetListenerTCP(network string, address *net.TCPAddr) (*net.TCPListener, err for i, l := range providedListeners { if isSameAddr(l.Addr(), address) { providedListeners = append(providedListeners[:i], providedListeners[i+1:]...) + needsUnlink := providedListenersToUnlink[i] + providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...) activeListeners = append(activeListeners, l) + activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink) return l.(*net.TCPListener), nil } } @@ -148,6 +164,7 @@ func GetListenerTCP(network string, address *net.TCPAddr) (*net.TCPListener, err return nil, err } activeListeners = append(activeListeners, l) + activeListenersToUnlink = append(activeListenersToUnlink, false) return l, nil } @@ -166,9 +183,15 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener, for i, l := range providedListeners { if isSameAddr(l.Addr(), address) { providedListeners = append(providedListeners[:i], providedListeners[i+1:]...) + needsUnlink := providedListenersToUnlink[i] + providedListenersToUnlink = append(providedListenersToUnlink[:i], providedListenersToUnlink[i+1:]...) + + activeListenersToUnlink = append(activeListenersToUnlink, needsUnlink) activeListeners = append(activeListeners, l) unixListener := l.(*net.UnixListener) - unixListener.SetUnlinkOnClose(true) + if needsUnlink { + unixListener.SetUnlinkOnClose(true) + } return unixListener, nil } } @@ -189,6 +212,7 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener, } activeListeners = append(activeListeners, l) + activeListenersToUnlink = append(activeListenersToUnlink, true) return l, nil } @@ -223,3 +247,11 @@ func getActiveListeners() []net.Listener { copy(listeners, activeListeners) return listeners } + +func getActiveListenersToUnlink() []bool { + mutex.Lock() + defer mutex.Unlock() + listenersToUnlink := make([]bool, len(activeListenersToUnlink)) + copy(listenersToUnlink, activeListenersToUnlink) + return listenersToUnlink +} diff --git a/modules/graceful/restart_unix.go b/modules/graceful/restart_unix.go index 2654ddfb94..1d0d1059e9 100644 --- a/modules/graceful/restart_unix.go +++ b/modules/graceful/restart_unix.go @@ -12,6 +12,7 @@ import ( "net" "os" "os/exec" + "strconv" "strings" "sync" "syscall" @@ -75,6 +76,20 @@ func RestartProcess() (int, error) { } env = append(env, fmt.Sprintf("%s=%d", listenFDs, len(listeners))) + sb := &strings.Builder{} + for i, unlink := range getActiveListenersToUnlink() { + if !unlink { + continue + } + _, _ = sb.WriteString(strconv.Itoa(i)) + _, _ = sb.WriteString(",") + } + unlinkStr := sb.String() + if len(unlinkStr) > 0 { + unlinkStr = unlinkStr[:len(unlinkStr)-1] + env = append(env, fmt.Sprintf("%s=%s", unlinkFDs, unlinkStr)) + } + allFiles := append([]*os.File{os.Stdin, os.Stdout, os.Stderr}, files...) process, err := os.StartProcess(argv0, os.Args, &os.ProcAttr{ Dir: originalWD,