Skip to content

Commit b3aa38b

Browse files
committed
Set Setpgid on child git processes (go-gitea#19865)
Backport go-gitea#19865 When Gitea is running as PID 1 git will occassionally orphan child processes leading to (defunct) processes. This PR simply sets Setpgid to true on these child processes meaning that these defunct processes will also be correctly reaped. Fix go-gitea#19077 Signed-off-by: Andrew Thornton <[email protected]>
1 parent 704f809 commit b3aa38b

File tree

9 files changed

+45
-2
lines changed

9 files changed

+45
-2
lines changed

cmd/serv.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"code.gitea.io/gitea/modules/log"
2525
"code.gitea.io/gitea/modules/pprof"
2626
"code.gitea.io/gitea/modules/private"
27+
"code.gitea.io/gitea/modules/process"
2728
"code.gitea.io/gitea/modules/setting"
2829
"code.gitea.io/gitea/services/lfs"
2930

@@ -247,7 +248,7 @@ func runServ(c *cli.Context) error {
247248
os.Setenv(models.EnvKeyID, fmt.Sprintf("%d", results.KeyID))
248249
os.Setenv(models.EnvAppURL, setting.AppURL)
249250

250-
//LFS token authentication
251+
// LFS token authentication
251252
if verb == lfsAuthenticateVerb {
252253
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, url.PathEscape(results.OwnerName), url.PathEscape(results.RepoName))
253254

@@ -306,6 +307,7 @@ func runServ(c *cli.Context) error {
306307
}
307308
}
308309

310+
process.SetSysProcAttribute(gitcmd)
309311
gitcmd.Dir = setting.RepoRootPath
310312
gitcmd.Stdout = os.Stdout
311313
gitcmd.Stdin = os.Stdin

modules/git/blame.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ func createBlameReader(ctx context.Context, dir string, command ...string) (*Bla
130130
cmd := exec.CommandContext(ctx, command[0], command[1:]...)
131131
cmd.Dir = dir
132132
cmd.Stderr = os.Stderr
133+
process.SetSysProcAttribute(cmd)
133134

134135
stdout, err := cmd.StdoutPipe()
135136
if err != nil {

modules/git/command.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ func (c *Command) RunWithContext(rc *RunContext) error {
188188
if goVersionLessThan115 {
189189
cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
190190
}
191+
process.SetSysProcAttribute(cmd)
191192
cmd.Dir = rc.Dir
192193
cmd.Stdout = rc.Stdout
193194
cmd.Stderr = rc.Stderr

modules/markup/external/external.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ func (p *Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.
119119
cmd.Stdin = input
120120
}
121121
cmd.Stdout = output
122+
process.SetSysProcAttribute(cmd)
123+
122124
if err := cmd.Run(); err != nil {
123125
return fmt.Errorf("%s render run command %s %v failed: %v", p.Name(), commands[0], args, err)
124126
}

modules/process/manager.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,13 @@ func (pm *Manager) ExecDirEnvStdIn(timeout time.Duration, dir, desc string, env
254254
if stdIn != nil {
255255
cmd.Stdin = stdIn
256256
}
257+
SetSysProcAttribute(cmd)
257258

258259
if err := cmd.Start(); err != nil {
259260
return "", "", err
260261
}
261262

262263
err := cmd.Wait()
263-
264264
if err != nil {
265265
err = &Error{
266266
PID: GetPID(ctx),

modules/process/manager_unix.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !windows
6+
7+
package process
8+
9+
import (
10+
"os/exec"
11+
"syscall"
12+
)
13+
14+
// SetSysProcAttribute sets the common SysProcAttrs for commands
15+
func SetSysProcAttribute(cmd *exec.Cmd) {
16+
// When Gitea runs SubProcessA -> SubProcessB and SubProcessA gets killed by context timeout, use setpgid to make sure the sub processes can be reaped instead of leaving defunct(zombie) processes.
17+
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
18+
}

modules/process/manager_windows.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build windows
6+
7+
package process
8+
9+
import (
10+
"os/exec"
11+
)
12+
13+
// SetSysProcAttribute sets the common SysProcAttrs for commands
14+
func SetSysProcAttribute(cmd *exec.Cmd) {
15+
// Do nothing
16+
}

modules/ssh/ssh.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ func sessionHandler(session ssh.Session) {
100100
}
101101
defer stdin.Close()
102102

103+
process.SetSysProcAttribute(cmd)
104+
103105
wg := &sync.WaitGroup{}
104106
wg.Add(2)
105107

services/mailer/mailer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ func (s *sendmailSender) Send(from string, to []string, msg io.WriterTo) error {
284284
if err != nil {
285285
return err
286286
}
287+
process.SetSysProcAttribute(cmd)
287288

288289
if err = cmd.Start(); err != nil {
289290
_ = pipe.Close()

0 commit comments

Comments
 (0)