// 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) }