Merge pull request #45216 from corhere/backport-20.10/containerd-fifo_v1.1

[20.10 backport] Upgrade containerd/fifo to v1.1.0
This commit is contained in:
Sebastiaan van Stijn 2023-03-30 00:46:19 +02:00 committed by GitHub
commit 83679bb638
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 69 additions and 72 deletions

View file

@ -135,7 +135,7 @@ google.golang.org/genproto 3f1135a288c9a07e340ae8ba4cc6
# containerd
github.com/containerd/containerd 96c5ae04b6784e180aaeee50fba715ac448ddb0d https://github.com/moby/containerd.git # docker-20.10 branch
github.com/containerd/fifo 0724c46b320cf96bb172a0550c19a4b1fca4dacb
github.com/containerd/fifo 151b205263c29d471e0d55c787d2ce9f5343fd46 # v1.1.0
github.com/containerd/continuity 5ad51c7aca47b8e742f5e6e7dc841d50f5f6affd # v0.3.0
github.com/containerd/cgroups b9de8a2212026c07cec67baf3323f1fc0121e048 # v1.0.1
github.com/containerd/console 2f1e3d2b6afd18e8b2077816c711205a0b4d8769 # v1.0.2

View file

@ -16,9 +16,7 @@
package fifo
import (
"errors"
)
import "errors"
var (
ErrClosed = errors.New("fifo closed")

View file

@ -1,3 +1,5 @@
//go:build !windows
/*
Copyright The containerd Authors.
@ -18,13 +20,13 @@ package fifo
import (
"context"
"fmt"
"io"
"os"
"runtime"
"sync"
"syscall"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@ -46,12 +48,12 @@ var leakCheckWg *sync.WaitGroup
func OpenFifoDup2(ctx context.Context, fn string, flag int, perm os.FileMode, fd int) (io.ReadWriteCloser, error) {
f, err := openFifo(ctx, fn, flag, perm)
if err != nil {
return nil, errors.Wrap(err, "fifo error")
return nil, fmt.Errorf("fifo error: %w", err)
}
if err := unix.Dup2(int(f.file.Fd()), fd); err != nil {
_ = f.Close()
return nil, errors.Wrap(err, "dup2 error")
return nil, fmt.Errorf("dup2 error: %w", err)
}
return f, nil
@ -60,22 +62,28 @@ func OpenFifoDup2(ctx context.Context, fn string, flag int, perm os.FileMode, fd
// OpenFifo opens a fifo. Returns io.ReadWriteCloser.
// Context can be used to cancel this function until open(2) has not returned.
// Accepted flags:
// - syscall.O_CREAT - create new fifo if one doesn't exist
// - syscall.O_RDONLY - open fifo only from reader side
// - syscall.O_WRONLY - open fifo only from writer side
// - syscall.O_RDWR - open fifo from both sides, never block on syscall level
// - syscall.O_NONBLOCK - return io.ReadWriteCloser even if other side of the
// - syscall.O_CREAT - create new fifo if one doesn't exist
// - syscall.O_RDONLY - open fifo only from reader side
// - syscall.O_WRONLY - open fifo only from writer side
// - syscall.O_RDWR - open fifo from both sides, never block on syscall level
// - syscall.O_NONBLOCK - return io.ReadWriteCloser even if other side of the
// fifo isn't open. read/write will be connected after the actual fifo is
// open or after fifo is closed.
func OpenFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
return openFifo(ctx, fn, flag, perm)
fifo, err := openFifo(ctx, fn, flag, perm)
if fifo == nil {
// Do not return a non-nil ReadWriteCloser((*fifo)(nil)) value
// as that can confuse callers.
return nil, err
}
return fifo, err
}
func openFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (*fifo, error) {
if _, err := os.Stat(fn); err != nil {
if os.IsNotExist(err) && flag&syscall.O_CREAT != 0 {
if err := mkfifo(fn, uint32(perm&os.ModePerm)); err != nil && !os.IsExist(err) {
return nil, errors.Wrapf(err, "error creating fifo %v", fn)
if err := syscall.Mkfifo(fn, uint32(perm&os.ModePerm)); err != nil && !os.IsExist(err) {
return nil, fmt.Errorf("error creating fifo %v: %w", fn, err)
}
} else {
return nil, err
@ -136,7 +144,7 @@ func openFifo(ctx context.Context, fn string, flag int, perm os.FileMode) (*fifo
case <-ctx.Done():
err = ctx.Err()
default:
err = errors.Errorf("fifo %v was closed before opening", h.Name())
err = fmt.Errorf("fifo %v was closed before opening", h.Name())
}
if file != nil {
file.Close()
@ -204,6 +212,10 @@ func (f *fifo) Write(b []byte) (int, error) {
// before open(2) has returned and fifo was never opened.
func (f *fifo) Close() (retErr error) {
for {
if f == nil {
return
}
select {
case <-f.closed:
f.handle.Close()

View file

@ -1,9 +1,14 @@
module github.com/containerd/fifo
go 1.13
go 1.18
require (
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.4.0
golang.org/x/sys v0.0.0-20191210023423-ac6580df4449
github.com/stretchr/testify v1.8.1
golang.org/x/sys v0.5.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View file

@ -1,4 +1,4 @@
// +build linux
//go:build linux
/*
Copyright The containerd Authors.
@ -23,11 +23,9 @@ import (
"os"
"sync"
"syscall"
"github.com/pkg/errors"
)
//nolint:golint
//nolint:revive
const O_PATH = 010000000
type handle struct {
@ -42,7 +40,7 @@ type handle struct {
func getHandle(fn string) (*handle, error) {
f, err := os.OpenFile(fn, O_PATH, 0)
if err != nil {
return nil, errors.Wrapf(err, "failed to open %v with O_PATH", fn)
return nil, fmt.Errorf("failed to open %v with O_PATH: %w", fn, err)
}
var (
@ -51,7 +49,7 @@ func getHandle(fn string) (*handle, error) {
)
if err := syscall.Fstat(int(fd), &stat); err != nil {
f.Close()
return nil, errors.Wrapf(err, "failed to stat handle %v", fd)
return nil, fmt.Errorf("failed to stat handle %v: %w", fd, err)
}
h := &handle{
@ -66,7 +64,7 @@ func getHandle(fn string) (*handle, error) {
// check /proc just in case
if _, err := os.Stat(h.procPath()); err != nil {
f.Close()
return nil, errors.Wrapf(err, "couldn't stat %v", h.procPath())
return nil, fmt.Errorf("couldn't stat %v: %w", h.procPath(), err)
}
return h, nil
@ -83,11 +81,11 @@ func (h *handle) Name() string {
func (h *handle) Path() (string, error) {
var stat syscall.Stat_t
if err := syscall.Stat(h.procPath(), &stat); err != nil {
return "", errors.Wrapf(err, "path %v could not be statted", h.procPath())
return "", fmt.Errorf("path %v could not be statted: %w", h.procPath(), err)
}
//nolint:unconvert
if uint64(stat.Dev) != h.dev || stat.Ino != h.ino {
return "", errors.Errorf("failed to verify handle %v/%v %v/%v", stat.Dev, h.dev, stat.Ino, h.ino)
return "", fmt.Errorf("failed to verify handle %v/%v %v/%v", stat.Dev, h.dev, stat.Ino, h.ino)
}
return h.procPath(), nil
}

View file

@ -1,4 +1,4 @@
// +build !linux
//go:build !linux && !windows
/*
Copyright The containerd Authors.
@ -19,9 +19,8 @@
package fifo
import (
"fmt"
"syscall"
"github.com/pkg/errors"
)
type handle struct {
@ -33,13 +32,13 @@ type handle struct {
func getHandle(fn string) (*handle, error) {
var stat syscall.Stat_t
if err := syscall.Stat(fn, &stat); err != nil {
return nil, errors.Wrapf(err, "failed to stat %v", fn)
return nil, fmt.Errorf("failed to stat %v: %w", fn, err)
}
h := &handle{
fn: fn,
dev: uint64(stat.Dev),
ino: uint64(stat.Ino),
dev: uint64(stat.Dev), //nolint:unconvert,nolintlint
ino: uint64(stat.Ino), //nolint:unconvert,nolintlint
}
return h, nil
@ -48,10 +47,10 @@ func getHandle(fn string) (*handle, error) {
func (h *handle) Path() (string, error) {
var stat syscall.Stat_t
if err := syscall.Stat(h.fn, &stat); err != nil {
return "", errors.Wrapf(err, "path %v could not be statted", h.fn)
return "", fmt.Errorf("path %v could not be statted: %w", h.fn, err)
}
if uint64(stat.Dev) != h.dev || uint64(stat.Ino) != h.ino {
return "", errors.Errorf("failed to verify handle %v/%v %v/%v for %v", stat.Dev, h.dev, stat.Ino, h.ino, h.fn)
if uint64(stat.Dev) != h.dev || uint64(stat.Ino) != h.ino { //nolint:unconvert,nolintlint
return "", fmt.Errorf("failed to verify handle %v/%v %v/%v for %v", stat.Dev, h.dev, stat.Ino, h.ino, h.fn)
}
return h.fn, nil
}

View file

@ -1,27 +0,0 @@
// +build solaris
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fifo
import (
"golang.org/x/sys/unix"
)
func mkfifo(path string, mode uint32) (err error) {
return unix.Mkfifo(path, mode)
}

View file

@ -1,4 +1,4 @@
// +build go1.12
//go:build !windows
/*
Copyright The containerd Authors.

View file

@ -1,7 +1,9 @@
### fifo
[![Build Status](https://travis-ci.org/containerd/fifo.svg?branch=master)](https://travis-ci.org/containerd/fifo)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/fifo)](https://pkg.go.dev/github.com/containerd/fifo)
[![Build Status](https://github.com/containerd/fifo/workflows/CI/badge.svg)](https://github.com/containerd/fifo/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/containerd/fifo/branch/master/graph/badge.svg)](https://codecov.io/gh/containerd/fifo)
[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/fifo)](https://goreportcard.com/report/github.com/containerd/fifo)
Go package for handling fifos in a sane way.

View file

@ -1,5 +1,3 @@
// +build !solaris
/*
Copyright The containerd Authors.
@ -18,8 +16,20 @@
package fifo
import "syscall"
import "os"
func mkfifo(path string, mode uint32) (err error) {
return syscall.Mkfifo(path, mode)
// IsFifo checks if a file is a (named pipe) fifo
// if the file does not exist then it returns false
func IsFifo(path string) (bool, error) {
stat, err := os.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
if stat.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
return true, nil
}
return false, nil
}