Skip to content
38 changes: 35 additions & 3 deletions modules/graceful/net_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) {
Expand All @@ -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))

Expand Down Expand Up @@ -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
}
}
Expand All @@ -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
}

Expand All @@ -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
}
}
Expand All @@ -189,6 +212,7 @@ func GetListenerUnix(network string, address *net.UnixAddr) (*net.UnixListener,
}

activeListeners = append(activeListeners, l)
activeListenersToUnlink = append(activeListenersToUnlink, true)
return l, nil
}

Expand Down Expand Up @@ -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
}
15 changes: 15 additions & 0 deletions modules/graceful/restart_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"net"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"syscall"
Expand Down Expand Up @@ -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,
Expand Down