blob: 5bb98d01d5acb0a31f383d3d361cd4acaebd88f7 [file] [log] [blame]
// 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)
}