File size: 2,246 Bytes
e36aeda | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | // Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"fmt"
"internal/testenv"
"io"
"os"
"syscall"
)
func gettid() int {
return syscall.Gettid()
}
func tidExists(tid int) (exists, supported bool, err error) {
// Open the magic proc status file for reading with the syscall package.
// We want to identify certain valid errors very precisely.
statusFile := fmt.Sprintf("/proc/self/task/%d/status", tid)
fd, err := syscall.Open(statusFile, syscall.O_RDONLY, 0)
if errno, ok := err.(syscall.Errno); ok {
if errno == syscall.ENOENT || errno == syscall.ESRCH {
return false, true, nil
}
}
if err != nil {
return false, false, err
}
status, err := io.ReadAll(os.NewFile(uintptr(fd), statusFile))
if err != nil {
return false, false, err
}
lines := bytes.Split(status, []byte{'\n'})
// Find the State line.
stateLineIdx := -1
for i, line := range lines {
if bytes.HasPrefix(line, []byte("State:")) {
stateLineIdx = i
break
}
}
if stateLineIdx < 0 {
// Malformed status file?
return false, false, fmt.Errorf("unexpected status file format: %s:\n%s", statusFile, status)
}
stateLine := bytes.SplitN(lines[stateLineIdx], []byte{':'}, 2)
if len(stateLine) != 2 {
// Malformed status file?
return false, false, fmt.Errorf("unexpected status file format: %s:\n%s", statusFile, status)
}
// Check if it's a zombie thread.
return !bytes.Contains(stateLine[1], []byte{'Z'}), true, nil
}
func getcwd() (string, error) {
if !syscall.ImplementsGetwd {
return "", nil
}
// Use the syscall to get the current working directory.
// This is imperative for checking for OS thread state
// after an unshare since os.Getwd might just check the
// environment, or use some other mechanism.
var buf [4096]byte
n, err := syscall.Getcwd(buf[:])
if err != nil {
return "", err
}
// Subtract one for null terminator.
return string(buf[:n-1]), nil
}
func unshareFs() error {
err := syscall.Unshare(syscall.CLONE_FS)
if testenv.SyscallIsNotSupported(err) {
return errNotPermitted
}
return err
}
func chdir(path string) error {
return syscall.Chdir(path)
}
|