Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/common-go/process/process.go
2498 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package process
6
7
import (
8
"context"
9
"errors"
10
"os"
11
12
"golang.org/x/sys/unix"
13
)
14
15
// IsNotChildProcess checks if an error returned by a command
16
// execution is an error related to no child processes running
17
// This can be seen, for instance, in short lived commands.
18
func IsNotChildProcess(err error) bool {
19
if err == nil {
20
return false
21
}
22
23
return (err.Error() == "wait: no child processes" || err.Error() == "waitid: no child processes")
24
}
25
26
var ErrForceKilled = errors.New("Process didn't terminate, so we sent SIGKILL")
27
28
// TerminateSync sends a SIGTERM to the given process and returns when the process has terminated or when the context was cancelled.
29
// When the context is cancelled this function sends a SIGKILL to the process and return immediately with ErrForceKilled.
30
func TerminateSync(ctx context.Context, pid int) error {
31
process, err := os.FindProcess(pid)
32
if err != nil { // never happens on UNIX
33
return err
34
}
35
err = process.Signal(unix.SIGTERM)
36
if err != nil {
37
if err == os.ErrProcessDone {
38
return nil
39
}
40
return err
41
}
42
terminated := make(chan error, 1)
43
go func() {
44
_, err := process.Wait()
45
terminated <- err
46
}()
47
select {
48
case err := <-terminated:
49
return err
50
case <-ctx.Done():
51
err = process.Kill()
52
if err != nil {
53
return err
54
}
55
return ErrForceKilled
56
}
57
}
58
59