forked from Shiloh/githaven
1d04e8641d
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 #19077 Signed-off-by: Andrew Thornton <art27@cantab.net>
81 lines
2.6 KiB
Go
81 lines
2.6 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package process
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
// Exec a command and use the default timeout.
|
|
func (pm *Manager) Exec(desc, cmdName string, args ...string) (string, string, error) {
|
|
return pm.ExecDir(DefaultContext, -1, "", desc, cmdName, args...)
|
|
}
|
|
|
|
// ExecTimeout a command and use a specific timeout duration.
|
|
func (pm *Manager) ExecTimeout(timeout time.Duration, desc, cmdName string, args ...string) (string, string, error) {
|
|
return pm.ExecDir(DefaultContext, timeout, "", desc, cmdName, args...)
|
|
}
|
|
|
|
// ExecDir a command and use the default timeout.
|
|
func (pm *Manager) ExecDir(ctx context.Context, timeout time.Duration, dir, desc, cmdName string, args ...string) (string, string, error) {
|
|
return pm.ExecDirEnv(ctx, timeout, dir, desc, nil, cmdName, args...)
|
|
}
|
|
|
|
// ExecDirEnv runs a command in given path and environment variables, and waits for its completion
|
|
// up to the given timeout (or DefaultTimeout if -1 is given).
|
|
// Returns its complete stdout and stderr
|
|
// outputs and an error, if any (including timeout)
|
|
func (pm *Manager) ExecDirEnv(ctx context.Context, timeout time.Duration, dir, desc string, env []string, cmdName string, args ...string) (string, string, error) {
|
|
return pm.ExecDirEnvStdIn(ctx, timeout, dir, desc, env, nil, cmdName, args...)
|
|
}
|
|
|
|
// ExecDirEnvStdIn runs a command in given path and environment variables with provided stdIN, and waits for its completion
|
|
// up to the given timeout (or DefaultTimeout if timeout <= 0 is given).
|
|
// Returns its complete stdout and stderr
|
|
// outputs and an error, if any (including timeout)
|
|
func (pm *Manager) ExecDirEnvStdIn(ctx context.Context, timeout time.Duration, dir, desc string, env []string, stdIn io.Reader, cmdName string, args ...string) (string, string, error) {
|
|
if timeout <= 0 {
|
|
timeout = 60 * time.Second
|
|
}
|
|
|
|
stdOut := new(bytes.Buffer)
|
|
stdErr := new(bytes.Buffer)
|
|
|
|
ctx, _, finished := pm.AddContextTimeout(ctx, timeout, desc)
|
|
defer finished()
|
|
|
|
cmd := exec.CommandContext(ctx, cmdName, args...)
|
|
cmd.Dir = dir
|
|
cmd.Env = env
|
|
cmd.Stdout = stdOut
|
|
cmd.Stderr = stdErr
|
|
if stdIn != nil {
|
|
cmd.Stdin = stdIn
|
|
}
|
|
SetSysProcAttribute(cmd)
|
|
|
|
if err := cmd.Start(); err != nil {
|
|
return "", "", err
|
|
}
|
|
|
|
err := cmd.Wait()
|
|
if err != nil {
|
|
err = &Error{
|
|
PID: GetPID(ctx),
|
|
Description: desc,
|
|
Err: err,
|
|
CtxErr: ctx.Err(),
|
|
Stdout: stdOut.String(),
|
|
Stderr: stdErr.String(),
|
|
}
|
|
}
|
|
|
|
return stdOut.String(), stdErr.String(), err
|
|
}
|