Ctrl K
ComunidadGuías…

utils/testmain_linux_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package utils

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"testing"

	"golang.org/x/sys/unix"
)

// TestMain keeps to this test binary the descriptors it was handed open on
// exec (a CI runner's step hands it some): each is made close on exec before
// any test runs, so a child a test starts holds the descriptors the test
// gives it and no others (TestMarkExitCountsOpenFilesNotDescriptors counts
// its child's files), whichever tests run and in whatever order. Go opens
// its own close on exec, and a test gives a child one of its own through
// ExtraFiles, which is dup'd for the child; no test here passes on one the
// binary was handed. None is closed.
func TestMain(m *testing.M) {
	flag.Parse()
	var kept []os.DirEntry
	kept, errDescriptorsKept = keepDescriptorsToSelf()
	if testing.Verbose() && len(kept) > 0 {
		fmt.Fprintf(os.Stderr, "this test binary was handed descriptors %s open on exec: made close on exec\n", descriptorsOf("/proc/self/fd", kept))
	}
	os.Exit(m.Run())
}

// errDescriptorsKept is why TestMain could not keep the binary's descriptors
// to itself, if it could not: a row whose child holds more than it was given
// says so.
var errDescriptorsKept error

// keepDescriptorsToSelf makes each descriptor of this process above stderr
// that is open on exec close on exec, and is those it made so.
func keepDescriptorsToSelf() ([]os.DirEntry, error) {
	fds, err := os.ReadDir("/proc/self/fd")
	if err != nil {
		return nil, err
	}
	var kept []os.DirEntry
	for _, e := range fds {
		fd, err := strconv.Atoi(e.Name())
		if err != nil || fd <= 2 {
			continue
		}
		flags, err := unix.FcntlInt(uintptr(fd), unix.F_GETFD, 0)
		switch {
		case errors.Is(err, unix.EBADF): // closed since it was listed: the listing's own
		case err != nil:
			return kept, fmt.Errorf("descriptor %d's flags: %w", fd, err)
		case flags&unix.FD_CLOEXEC == 0:
			if _, err := unix.FcntlInt(uintptr(fd), unix.F_SETFD, flags|unix.FD_CLOEXEC); err != nil {
				return kept, fmt.Errorf("descriptor %d made close on exec: %w", fd, err)
			}
			kept = append(kept, e)
		}
	}
	return kept, nil
}

// descriptorsOf is listed descriptors fds of fd directory dir with what each
// names, for a row to say what a process held.
func descriptorsOf(dir string, fds []os.DirEntry) string {
	var named []string
	for _, e := range fds {
		target, err := os.Readlink(filepath.Join(dir, e.Name()))
		if err != nil {
			target = "(" + err.Error() + ")"
		}
		named = append(named, e.Name()+" "+target)
	}
	return "[" + strings.Join(named, ", ") + "]"
}