Source file src/runtime/testdata/testprog/syscalls_linux.go

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

View as plain text