Use ParseSignal and AtomicWriteFile functions from containerd
Containerd has its own ParseSignal and AtomicWriteFile implementation. So there's no need to use these function from github.com/docker/docker. Signed-off-by: Shengjing Zhu <i@zhsj.me>
This commit is contained in:
parent
95f564f95b
commit
c6729fe0c4
@ -22,7 +22,6 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
eventtypes "github.com/containerd/containerd/api/events"
|
eventtypes "github.com/containerd/containerd/api/events"
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/docker/docker/pkg/signal"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
@ -134,7 +133,7 @@ func (c *criService) stopContainer(ctx context.Context, container containerstore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sig, err := signal.ParseSignal(stopSignal)
|
sig, err := containerd.ParseSignal(stopSignal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal)
|
return errors.Wrapf(err, "failed to parse stop signal %q", stopSignal)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/containerd/continuity"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
)
|
)
|
||||||
@ -160,7 +160,7 @@ func StoreStatus(root, id string, status Status) (StatusStorage, error) {
|
|||||||
return nil, errors.Wrap(err, "failed to encode status")
|
return nil, errors.Wrap(err, "failed to encode status")
|
||||||
}
|
}
|
||||||
path := filepath.Join(root, "status")
|
path := filepath.Join(root, "status")
|
||||||
if err := ioutils.AtomicWriteFile(path, data, 0600); err != nil {
|
if err := continuity.AtomicWriteFile(path, data, 0600); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to checkpoint status to %q", path)
|
return nil, errors.Wrapf(err, "failed to checkpoint status to %q", path)
|
||||||
}
|
}
|
||||||
return &statusStorage{
|
return &statusStorage{
|
||||||
@ -209,7 +209,7 @@ func (s *statusStorage) UpdateSync(u UpdateFunc) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to encode status")
|
return errors.Wrap(err, "failed to encode status")
|
||||||
}
|
}
|
||||||
if err := ioutils.AtomicWriteFile(s.path, data, 0600); err != nil {
|
if err := continuity.AtomicWriteFile(s.path, data, 0600); err != nil {
|
||||||
return errors.Wrapf(err, "failed to checkpoint status to %q", s.path)
|
return errors.Wrapf(err, "failed to checkpoint status to %q", s.path)
|
||||||
}
|
}
|
||||||
s.status = newStatus
|
s.status = newStatus
|
||||||
|
51
vendor/github.com/docker/docker/pkg/ioutils/buffer.go
generated
vendored
51
vendor/github.com/docker/docker/pkg/ioutils/buffer.go
generated
vendored
@ -1,51 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errBufferFull = errors.New("buffer is full")
|
|
||||||
|
|
||||||
type fixedBuffer struct {
|
|
||||||
buf []byte
|
|
||||||
pos int
|
|
||||||
lastRead int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) Write(p []byte) (int, error) {
|
|
||||||
n := copy(b.buf[b.pos:cap(b.buf)], p)
|
|
||||||
b.pos += n
|
|
||||||
|
|
||||||
if n < len(p) {
|
|
||||||
if b.pos == cap(b.buf) {
|
|
||||||
return n, errBufferFull
|
|
||||||
}
|
|
||||||
return n, io.ErrShortWrite
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) Read(p []byte) (int, error) {
|
|
||||||
n := copy(p, b.buf[b.lastRead:b.pos])
|
|
||||||
b.lastRead += n
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) Len() int {
|
|
||||||
return b.pos - b.lastRead
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) Cap() int {
|
|
||||||
return cap(b.buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) Reset() {
|
|
||||||
b.pos = 0
|
|
||||||
b.lastRead = 0
|
|
||||||
b.buf = b.buf[:0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *fixedBuffer) String() string {
|
|
||||||
return string(b.buf[b.lastRead:b.pos])
|
|
||||||
}
|
|
186
vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go
generated
vendored
186
vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go
generated
vendored
@ -1,186 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// maxCap is the highest capacity to use in byte slices that buffer data.
|
|
||||||
const maxCap = 1e6
|
|
||||||
|
|
||||||
// minCap is the lowest capacity to use in byte slices that buffer data
|
|
||||||
const minCap = 64
|
|
||||||
|
|
||||||
// blockThreshold is the minimum number of bytes in the buffer which will cause
|
|
||||||
// a write to BytesPipe to block when allocating a new slice.
|
|
||||||
const blockThreshold = 1e6
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrClosed is returned when Write is called on a closed BytesPipe.
|
|
||||||
ErrClosed = errors.New("write to closed BytesPipe")
|
|
||||||
|
|
||||||
bufPools = make(map[int]*sync.Pool)
|
|
||||||
bufPoolsLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue).
|
|
||||||
// All written data may be read at most once. Also, BytesPipe allocates
|
|
||||||
// and releases new byte slices to adjust to current needs, so the buffer
|
|
||||||
// won't be overgrown after peak loads.
|
|
||||||
type BytesPipe struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
wait *sync.Cond
|
|
||||||
buf []*fixedBuffer
|
|
||||||
bufLen int
|
|
||||||
closeErr error // error to return from next Read. set to nil if not closed.
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBytesPipe creates new BytesPipe, initialized by specified slice.
|
|
||||||
// If buf is nil, then it will be initialized with slice which cap is 64.
|
|
||||||
// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf).
|
|
||||||
func NewBytesPipe() *BytesPipe {
|
|
||||||
bp := &BytesPipe{}
|
|
||||||
bp.buf = append(bp.buf, getBuffer(minCap))
|
|
||||||
bp.wait = sync.NewCond(&bp.mu)
|
|
||||||
return bp
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write writes p to BytesPipe.
|
|
||||||
// It can allocate new []byte slices in a process of writing.
|
|
||||||
func (bp *BytesPipe) Write(p []byte) (int, error) {
|
|
||||||
bp.mu.Lock()
|
|
||||||
|
|
||||||
written := 0
|
|
||||||
loop0:
|
|
||||||
for {
|
|
||||||
if bp.closeErr != nil {
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return written, ErrClosed
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(bp.buf) == 0 {
|
|
||||||
bp.buf = append(bp.buf, getBuffer(64))
|
|
||||||
}
|
|
||||||
// get the last buffer
|
|
||||||
b := bp.buf[len(bp.buf)-1]
|
|
||||||
|
|
||||||
n, err := b.Write(p)
|
|
||||||
written += n
|
|
||||||
bp.bufLen += n
|
|
||||||
|
|
||||||
// errBufferFull is an error we expect to get if the buffer is full
|
|
||||||
if err != nil && err != errBufferFull {
|
|
||||||
bp.wait.Broadcast()
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return written, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there was enough room to write all then break
|
|
||||||
if len(p) == n {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// more data: write to the next slice
|
|
||||||
p = p[n:]
|
|
||||||
|
|
||||||
// make sure the buffer doesn't grow too big from this write
|
|
||||||
for bp.bufLen >= blockThreshold {
|
|
||||||
bp.wait.Wait()
|
|
||||||
if bp.closeErr != nil {
|
|
||||||
continue loop0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add new byte slice to the buffers slice and continue writing
|
|
||||||
nextCap := b.Cap() * 2
|
|
||||||
if nextCap > maxCap {
|
|
||||||
nextCap = maxCap
|
|
||||||
}
|
|
||||||
bp.buf = append(bp.buf, getBuffer(nextCap))
|
|
||||||
}
|
|
||||||
bp.wait.Broadcast()
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return written, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloseWithError causes further reads from a BytesPipe to return immediately.
|
|
||||||
func (bp *BytesPipe) CloseWithError(err error) error {
|
|
||||||
bp.mu.Lock()
|
|
||||||
if err != nil {
|
|
||||||
bp.closeErr = err
|
|
||||||
} else {
|
|
||||||
bp.closeErr = io.EOF
|
|
||||||
}
|
|
||||||
bp.wait.Broadcast()
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close causes further reads from a BytesPipe to return immediately.
|
|
||||||
func (bp *BytesPipe) Close() error {
|
|
||||||
return bp.CloseWithError(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read reads bytes from BytesPipe.
|
|
||||||
// Data could be read only once.
|
|
||||||
func (bp *BytesPipe) Read(p []byte) (n int, err error) {
|
|
||||||
bp.mu.Lock()
|
|
||||||
if bp.bufLen == 0 {
|
|
||||||
if bp.closeErr != nil {
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return 0, bp.closeErr
|
|
||||||
}
|
|
||||||
bp.wait.Wait()
|
|
||||||
if bp.bufLen == 0 && bp.closeErr != nil {
|
|
||||||
err := bp.closeErr
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for bp.bufLen > 0 {
|
|
||||||
b := bp.buf[0]
|
|
||||||
read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error
|
|
||||||
n += read
|
|
||||||
bp.bufLen -= read
|
|
||||||
|
|
||||||
if b.Len() == 0 {
|
|
||||||
// it's empty so return it to the pool and move to the next one
|
|
||||||
returnBuffer(b)
|
|
||||||
bp.buf[0] = nil
|
|
||||||
bp.buf = bp.buf[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(p) == read {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
p = p[read:]
|
|
||||||
}
|
|
||||||
|
|
||||||
bp.wait.Broadcast()
|
|
||||||
bp.mu.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func returnBuffer(b *fixedBuffer) {
|
|
||||||
b.Reset()
|
|
||||||
bufPoolsLock.Lock()
|
|
||||||
pool := bufPools[b.Cap()]
|
|
||||||
bufPoolsLock.Unlock()
|
|
||||||
if pool != nil {
|
|
||||||
pool.Put(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBuffer(size int) *fixedBuffer {
|
|
||||||
bufPoolsLock.Lock()
|
|
||||||
pool, ok := bufPools[size]
|
|
||||||
if !ok {
|
|
||||||
pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }}
|
|
||||||
bufPools[size] = pool
|
|
||||||
}
|
|
||||||
bufPoolsLock.Unlock()
|
|
||||||
return pool.Get().(*fixedBuffer)
|
|
||||||
}
|
|
162
vendor/github.com/docker/docker/pkg/ioutils/fswriters.go
generated
vendored
162
vendor/github.com/docker/docker/pkg/ioutils/fswriters.go
generated
vendored
@ -1,162 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a
|
|
||||||
// temporary file and closing it atomically changes the temporary file to
|
|
||||||
// destination path. Writing and closing concurrently is not allowed.
|
|
||||||
func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) {
|
|
||||||
f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
abspath, err := filepath.Abs(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &atomicFileWriter{
|
|
||||||
f: f,
|
|
||||||
fn: abspath,
|
|
||||||
perm: perm,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AtomicWriteFile atomically writes data to a file named by filename.
|
|
||||||
func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
|
|
||||||
f, err := NewAtomicFileWriter(filename, perm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
n, err := f.Write(data)
|
|
||||||
if err == nil && n < len(data) {
|
|
||||||
err = io.ErrShortWrite
|
|
||||||
f.(*atomicFileWriter).writeErr = err
|
|
||||||
}
|
|
||||||
if err1 := f.Close(); err == nil {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type atomicFileWriter struct {
|
|
||||||
f *os.File
|
|
||||||
fn string
|
|
||||||
writeErr error
|
|
||||||
perm os.FileMode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *atomicFileWriter) Write(dt []byte) (int, error) {
|
|
||||||
n, err := w.f.Write(dt)
|
|
||||||
if err != nil {
|
|
||||||
w.writeErr = err
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *atomicFileWriter) Close() (retErr error) {
|
|
||||||
defer func() {
|
|
||||||
if retErr != nil || w.writeErr != nil {
|
|
||||||
os.Remove(w.f.Name())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err := w.f.Sync(); err != nil {
|
|
||||||
w.f.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.f.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := os.Chmod(w.f.Name(), w.perm); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if w.writeErr == nil {
|
|
||||||
return os.Rename(w.f.Name(), w.fn)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AtomicWriteSet is used to atomically write a set
|
|
||||||
// of files and ensure they are visible at the same time.
|
|
||||||
// Must be committed to a new directory.
|
|
||||||
type AtomicWriteSet struct {
|
|
||||||
root string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewAtomicWriteSet creates a new atomic write set to
|
|
||||||
// atomically create a set of files. The given directory
|
|
||||||
// is used as the base directory for storing files before
|
|
||||||
// commit. If no temporary directory is given the system
|
|
||||||
// default is used.
|
|
||||||
func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) {
|
|
||||||
td, err := ioutil.TempDir(tmpDir, "write-set-")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &AtomicWriteSet{
|
|
||||||
root: td,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteFile writes a file to the set, guaranteeing the file
|
|
||||||
// has been synced.
|
|
||||||
func (ws *AtomicWriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error {
|
|
||||||
f, err := ws.FileWriter(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
n, err := f.Write(data)
|
|
||||||
if err == nil && n < len(data) {
|
|
||||||
err = io.ErrShortWrite
|
|
||||||
}
|
|
||||||
if err1 := f.Close(); err == nil {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncFileCloser struct {
|
|
||||||
*os.File
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w syncFileCloser) Close() error {
|
|
||||||
err := w.File.Sync()
|
|
||||||
if err1 := w.File.Close(); err == nil {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileWriter opens a file writer inside the set. The file
|
|
||||||
// should be synced and closed before calling commit.
|
|
||||||
func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) {
|
|
||||||
f, err := os.OpenFile(filepath.Join(ws.root, name), flag, perm)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return syncFileCloser{f}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel cancels the set and removes all temporary data
|
|
||||||
// created in the set.
|
|
||||||
func (ws *AtomicWriteSet) Cancel() error {
|
|
||||||
return os.RemoveAll(ws.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit moves all created files to the target directory. The
|
|
||||||
// target directory must not exist and the parent of the target
|
|
||||||
// directory must exist.
|
|
||||||
func (ws *AtomicWriteSet) Commit(target string) error {
|
|
||||||
return os.Rename(ws.root, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the location the set is writing to.
|
|
||||||
func (ws *AtomicWriteSet) String() string {
|
|
||||||
return ws.root
|
|
||||||
}
|
|
154
vendor/github.com/docker/docker/pkg/ioutils/readers.go
generated
vendored
154
vendor/github.com/docker/docker/pkg/ioutils/readers.go
generated
vendored
@ -1,154 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
)
|
|
||||||
|
|
||||||
type readCloserWrapper struct {
|
|
||||||
io.Reader
|
|
||||||
closer func() error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *readCloserWrapper) Close() error {
|
|
||||||
return r.closer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewReadCloserWrapper returns a new io.ReadCloser.
|
|
||||||
func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser {
|
|
||||||
return &readCloserWrapper{
|
|
||||||
Reader: r,
|
|
||||||
closer: closer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type readerErrWrapper struct {
|
|
||||||
reader io.Reader
|
|
||||||
closer func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *readerErrWrapper) Read(p []byte) (int, error) {
|
|
||||||
n, err := r.reader.Read(p)
|
|
||||||
if err != nil {
|
|
||||||
r.closer()
|
|
||||||
}
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewReaderErrWrapper returns a new io.Reader.
|
|
||||||
func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader {
|
|
||||||
return &readerErrWrapper{
|
|
||||||
reader: r,
|
|
||||||
closer: closer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashData returns the sha256 sum of src.
|
|
||||||
func HashData(src io.Reader) (string, error) {
|
|
||||||
h := sha256.New()
|
|
||||||
if _, err := io.Copy(h, src); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return "sha256:" + hex.EncodeToString(h.Sum(nil)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnEOFReader wraps an io.ReadCloser and a function
|
|
||||||
// the function will run at the end of file or close the file.
|
|
||||||
type OnEOFReader struct {
|
|
||||||
Rc io.ReadCloser
|
|
||||||
Fn func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *OnEOFReader) Read(p []byte) (n int, err error) {
|
|
||||||
n, err = r.Rc.Read(p)
|
|
||||||
if err == io.EOF {
|
|
||||||
r.runFunc()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the file and run the function.
|
|
||||||
func (r *OnEOFReader) Close() error {
|
|
||||||
err := r.Rc.Close()
|
|
||||||
r.runFunc()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *OnEOFReader) runFunc() {
|
|
||||||
if fn := r.Fn; fn != nil {
|
|
||||||
fn()
|
|
||||||
r.Fn = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancelReadCloser wraps an io.ReadCloser with a context for cancelling read
|
|
||||||
// operations.
|
|
||||||
type cancelReadCloser struct {
|
|
||||||
cancel func()
|
|
||||||
pR *io.PipeReader // Stream to read from
|
|
||||||
pW *io.PipeWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewCancelReadCloser creates a wrapper that closes the ReadCloser when the
|
|
||||||
// context is cancelled. The returned io.ReadCloser must be closed when it is
|
|
||||||
// no longer needed.
|
|
||||||
func NewCancelReadCloser(ctx context.Context, in io.ReadCloser) io.ReadCloser {
|
|
||||||
pR, pW := io.Pipe()
|
|
||||||
|
|
||||||
// Create a context used to signal when the pipe is closed
|
|
||||||
doneCtx, cancel := context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
p := &cancelReadCloser{
|
|
||||||
cancel: cancel,
|
|
||||||
pR: pR,
|
|
||||||
pW: pW,
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
_, err := io.Copy(pW, in)
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
// If the context was closed, p.closeWithError
|
|
||||||
// was already called. Calling it again would
|
|
||||||
// change the error that Read returns.
|
|
||||||
default:
|
|
||||||
p.closeWithError(err)
|
|
||||||
}
|
|
||||||
in.Close()
|
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
p.closeWithError(ctx.Err())
|
|
||||||
case <-doneCtx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read wraps the Read method of the pipe that provides data from the wrapped
|
|
||||||
// ReadCloser.
|
|
||||||
func (p *cancelReadCloser) Read(buf []byte) (n int, err error) {
|
|
||||||
return p.pR.Read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// closeWithError closes the wrapper and its underlying reader. It will
|
|
||||||
// cause future calls to Read to return err.
|
|
||||||
func (p *cancelReadCloser) closeWithError(err error) {
|
|
||||||
p.pW.CloseWithError(err)
|
|
||||||
p.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the wrapper its underlying reader. It will cause
|
|
||||||
// future calls to Read to return io.EOF.
|
|
||||||
func (p *cancelReadCloser) Close() error {
|
|
||||||
p.closeWithError(io.EOF)
|
|
||||||
return nil
|
|
||||||
}
|
|
10
vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go
generated
vendored
10
vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
package ioutils
|
|
||||||
|
|
||||||
import "io/ioutil"
|
|
||||||
|
|
||||||
// TempDir on Unix systems is equivalent to ioutil.TempDir.
|
|
||||||
func TempDir(dir, prefix string) (string, error) {
|
|
||||||
return ioutil.TempDir(dir, prefix)
|
|
||||||
}
|
|
18
vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go
generated
vendored
18
vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go
generated
vendored
@ -1,18 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/longpath"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TempDir is the equivalent of ioutil.TempDir, except that the result is in Windows longpath format.
|
|
||||||
func TempDir(dir, prefix string) (string, error) {
|
|
||||||
tempDir, err := ioutil.TempDir(dir, prefix)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return longpath.AddPrefix(tempDir), nil
|
|
||||||
}
|
|
92
vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go
generated
vendored
92
vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go
generated
vendored
@ -1,92 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WriteFlusher wraps the Write and Flush operation ensuring that every write
|
|
||||||
// is a flush. In addition, the Close method can be called to intercept
|
|
||||||
// Read/Write calls if the targets lifecycle has already ended.
|
|
||||||
type WriteFlusher struct {
|
|
||||||
w io.Writer
|
|
||||||
flusher flusher
|
|
||||||
flushed chan struct{}
|
|
||||||
flushedOnce sync.Once
|
|
||||||
closed chan struct{}
|
|
||||||
closeLock sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
type flusher interface {
|
|
||||||
Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
var errWriteFlusherClosed = io.EOF
|
|
||||||
|
|
||||||
func (wf *WriteFlusher) Write(b []byte) (n int, err error) {
|
|
||||||
select {
|
|
||||||
case <-wf.closed:
|
|
||||||
return 0, errWriteFlusherClosed
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = wf.w.Write(b)
|
|
||||||
wf.Flush() // every write is a flush.
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush the stream immediately.
|
|
||||||
func (wf *WriteFlusher) Flush() {
|
|
||||||
select {
|
|
||||||
case <-wf.closed:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
wf.flushedOnce.Do(func() {
|
|
||||||
close(wf.flushed)
|
|
||||||
})
|
|
||||||
wf.flusher.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flushed returns the state of flushed.
|
|
||||||
// If it's flushed, return true, or else it return false.
|
|
||||||
func (wf *WriteFlusher) Flushed() bool {
|
|
||||||
// BUG(stevvooe): Remove this method. Its use is inherently racy. Seems to
|
|
||||||
// be used to detect whether or a response code has been issued or not.
|
|
||||||
// Another hook should be used instead.
|
|
||||||
var flushed bool
|
|
||||||
select {
|
|
||||||
case <-wf.flushed:
|
|
||||||
flushed = true
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return flushed
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the write flusher, disallowing any further writes to the
|
|
||||||
// target. After the flusher is closed, all calls to write or flush will
|
|
||||||
// result in an error.
|
|
||||||
func (wf *WriteFlusher) Close() error {
|
|
||||||
wf.closeLock.Lock()
|
|
||||||
defer wf.closeLock.Unlock()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-wf.closed:
|
|
||||||
return errWriteFlusherClosed
|
|
||||||
default:
|
|
||||||
close(wf.closed)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWriteFlusher returns a new WriteFlusher.
|
|
||||||
func NewWriteFlusher(w io.Writer) *WriteFlusher {
|
|
||||||
var fl flusher
|
|
||||||
if f, ok := w.(flusher); ok {
|
|
||||||
fl = f
|
|
||||||
} else {
|
|
||||||
fl = &NopFlusher{}
|
|
||||||
}
|
|
||||||
return &WriteFlusher{w: w, flusher: fl, closed: make(chan struct{}), flushed: make(chan struct{})}
|
|
||||||
}
|
|
66
vendor/github.com/docker/docker/pkg/ioutils/writers.go
generated
vendored
66
vendor/github.com/docker/docker/pkg/ioutils/writers.go
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
package ioutils
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
// NopWriter represents a type which write operation is nop.
|
|
||||||
type NopWriter struct{}
|
|
||||||
|
|
||||||
func (*NopWriter) Write(buf []byte) (int, error) {
|
|
||||||
return len(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type nopWriteCloser struct {
|
|
||||||
io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *nopWriteCloser) Close() error { return nil }
|
|
||||||
|
|
||||||
// NopWriteCloser returns a nopWriteCloser.
|
|
||||||
func NopWriteCloser(w io.Writer) io.WriteCloser {
|
|
||||||
return &nopWriteCloser{w}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NopFlusher represents a type which flush operation is nop.
|
|
||||||
type NopFlusher struct{}
|
|
||||||
|
|
||||||
// Flush is a nop operation.
|
|
||||||
func (f *NopFlusher) Flush() {}
|
|
||||||
|
|
||||||
type writeCloserWrapper struct {
|
|
||||||
io.Writer
|
|
||||||
closer func() error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *writeCloserWrapper) Close() error {
|
|
||||||
return r.closer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWriteCloserWrapper returns a new io.WriteCloser.
|
|
||||||
func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser {
|
|
||||||
return &writeCloserWrapper{
|
|
||||||
Writer: r,
|
|
||||||
closer: closer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteCounter wraps a concrete io.Writer and hold a count of the number
|
|
||||||
// of bytes written to the writer during a "session".
|
|
||||||
// This can be convenient when write return is masked
|
|
||||||
// (e.g., json.Encoder.Encode())
|
|
||||||
type WriteCounter struct {
|
|
||||||
Count int64
|
|
||||||
Writer io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWriteCounter returns a new WriteCounter.
|
|
||||||
func NewWriteCounter(w io.Writer) *WriteCounter {
|
|
||||||
return &WriteCounter{
|
|
||||||
Writer: w,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wc *WriteCounter) Write(p []byte) (count int, err error) {
|
|
||||||
count, err = wc.Writer.Write(p)
|
|
||||||
wc.Count += int64(count)
|
|
||||||
return
|
|
||||||
}
|
|
1
vendor/github.com/docker/docker/pkg/signal/README.md
generated
vendored
1
vendor/github.com/docker/docker/pkg/signal/README.md
generated
vendored
@ -1 +0,0 @@
|
|||||||
This package provides helper functions for dealing with signals across various operating systems
|
|
54
vendor/github.com/docker/docker/pkg/signal/signal.go
generated
vendored
54
vendor/github.com/docker/docker/pkg/signal/signal.go
generated
vendored
@ -1,54 +0,0 @@
|
|||||||
// Package signal provides helper functions for dealing with signals across
|
|
||||||
// various operating systems.
|
|
||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CatchAll catches all signals and relays them to the specified channel.
|
|
||||||
func CatchAll(sigc chan os.Signal) {
|
|
||||||
handledSigs := []os.Signal{}
|
|
||||||
for _, s := range SignalMap {
|
|
||||||
handledSigs = append(handledSigs, s)
|
|
||||||
}
|
|
||||||
signal.Notify(sigc, handledSigs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopCatch stops catching the signals and closes the specified channel.
|
|
||||||
func StopCatch(sigc chan os.Signal) {
|
|
||||||
signal.Stop(sigc)
|
|
||||||
close(sigc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseSignal translates a string to a valid syscall signal.
|
|
||||||
// It returns an error if the signal map doesn't include the given signal.
|
|
||||||
func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
|
||||||
s, err := strconv.Atoi(rawSignal)
|
|
||||||
if err == nil {
|
|
||||||
if s == 0 {
|
|
||||||
return -1, fmt.Errorf("Invalid signal: %s", rawSignal)
|
|
||||||
}
|
|
||||||
return syscall.Signal(s), nil
|
|
||||||
}
|
|
||||||
signal, ok := SignalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
|
|
||||||
if !ok {
|
|
||||||
return -1, fmt.Errorf("Invalid signal: %s", rawSignal)
|
|
||||||
}
|
|
||||||
return signal, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidSignalForPlatform returns true if a signal is valid on the platform
|
|
||||||
func ValidSignalForPlatform(sig syscall.Signal) bool {
|
|
||||||
for _, v := range SignalMap {
|
|
||||||
if v == sig {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
41
vendor/github.com/docker/docker/pkg/signal/signal_darwin.go
generated
vendored
41
vendor/github.com/docker/docker/pkg/signal/signal_darwin.go
generated
vendored
@ -1,41 +0,0 @@
|
|||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is a map of Darwin signals.
|
|
||||||
var SignalMap = map[string]syscall.Signal{
|
|
||||||
"ABRT": syscall.SIGABRT,
|
|
||||||
"ALRM": syscall.SIGALRM,
|
|
||||||
"BUG": syscall.SIGBUS,
|
|
||||||
"CHLD": syscall.SIGCHLD,
|
|
||||||
"CONT": syscall.SIGCONT,
|
|
||||||
"EMT": syscall.SIGEMT,
|
|
||||||
"FPE": syscall.SIGFPE,
|
|
||||||
"HUP": syscall.SIGHUP,
|
|
||||||
"ILL": syscall.SIGILL,
|
|
||||||
"INFO": syscall.SIGINFO,
|
|
||||||
"INT": syscall.SIGINT,
|
|
||||||
"IO": syscall.SIGIO,
|
|
||||||
"IOT": syscall.SIGIOT,
|
|
||||||
"KILL": syscall.SIGKILL,
|
|
||||||
"PIPE": syscall.SIGPIPE,
|
|
||||||
"PROF": syscall.SIGPROF,
|
|
||||||
"QUIT": syscall.SIGQUIT,
|
|
||||||
"SEGV": syscall.SIGSEGV,
|
|
||||||
"STOP": syscall.SIGSTOP,
|
|
||||||
"SYS": syscall.SIGSYS,
|
|
||||||
"TERM": syscall.SIGTERM,
|
|
||||||
"TRAP": syscall.SIGTRAP,
|
|
||||||
"TSTP": syscall.SIGTSTP,
|
|
||||||
"TTIN": syscall.SIGTTIN,
|
|
||||||
"TTOU": syscall.SIGTTOU,
|
|
||||||
"URG": syscall.SIGURG,
|
|
||||||
"USR1": syscall.SIGUSR1,
|
|
||||||
"USR2": syscall.SIGUSR2,
|
|
||||||
"VTALRM": syscall.SIGVTALRM,
|
|
||||||
"WINCH": syscall.SIGWINCH,
|
|
||||||
"XCPU": syscall.SIGXCPU,
|
|
||||||
"XFSZ": syscall.SIGXFSZ,
|
|
||||||
}
|
|
43
vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go
generated
vendored
43
vendor/github.com/docker/docker/pkg/signal/signal_freebsd.go
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is a map of FreeBSD signals.
|
|
||||||
var SignalMap = map[string]syscall.Signal{
|
|
||||||
"ABRT": syscall.SIGABRT,
|
|
||||||
"ALRM": syscall.SIGALRM,
|
|
||||||
"BUF": syscall.SIGBUS,
|
|
||||||
"CHLD": syscall.SIGCHLD,
|
|
||||||
"CONT": syscall.SIGCONT,
|
|
||||||
"EMT": syscall.SIGEMT,
|
|
||||||
"FPE": syscall.SIGFPE,
|
|
||||||
"HUP": syscall.SIGHUP,
|
|
||||||
"ILL": syscall.SIGILL,
|
|
||||||
"INFO": syscall.SIGINFO,
|
|
||||||
"INT": syscall.SIGINT,
|
|
||||||
"IO": syscall.SIGIO,
|
|
||||||
"IOT": syscall.SIGIOT,
|
|
||||||
"KILL": syscall.SIGKILL,
|
|
||||||
"LWP": syscall.SIGLWP,
|
|
||||||
"PIPE": syscall.SIGPIPE,
|
|
||||||
"PROF": syscall.SIGPROF,
|
|
||||||
"QUIT": syscall.SIGQUIT,
|
|
||||||
"SEGV": syscall.SIGSEGV,
|
|
||||||
"STOP": syscall.SIGSTOP,
|
|
||||||
"SYS": syscall.SIGSYS,
|
|
||||||
"TERM": syscall.SIGTERM,
|
|
||||||
"THR": syscall.SIGTHR,
|
|
||||||
"TRAP": syscall.SIGTRAP,
|
|
||||||
"TSTP": syscall.SIGTSTP,
|
|
||||||
"TTIN": syscall.SIGTTIN,
|
|
||||||
"TTOU": syscall.SIGTTOU,
|
|
||||||
"URG": syscall.SIGURG,
|
|
||||||
"USR1": syscall.SIGUSR1,
|
|
||||||
"USR2": syscall.SIGUSR2,
|
|
||||||
"VTALRM": syscall.SIGVTALRM,
|
|
||||||
"WINCH": syscall.SIGWINCH,
|
|
||||||
"XCPU": syscall.SIGXCPU,
|
|
||||||
"XFSZ": syscall.SIGXFSZ,
|
|
||||||
}
|
|
81
vendor/github.com/docker/docker/pkg/signal/signal_linux.go
generated
vendored
81
vendor/github.com/docker/docker/pkg/signal/signal_linux.go
generated
vendored
@ -1,81 +0,0 @@
|
|||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
sigrtmin = 34
|
|
||||||
sigrtmax = 64
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is a map of Linux signals.
|
|
||||||
var SignalMap = map[string]syscall.Signal{
|
|
||||||
"ABRT": unix.SIGABRT,
|
|
||||||
"ALRM": unix.SIGALRM,
|
|
||||||
"BUS": unix.SIGBUS,
|
|
||||||
"CHLD": unix.SIGCHLD,
|
|
||||||
"CLD": unix.SIGCLD,
|
|
||||||
"CONT": unix.SIGCONT,
|
|
||||||
"FPE": unix.SIGFPE,
|
|
||||||
"HUP": unix.SIGHUP,
|
|
||||||
"ILL": unix.SIGILL,
|
|
||||||
"INT": unix.SIGINT,
|
|
||||||
"IO": unix.SIGIO,
|
|
||||||
"IOT": unix.SIGIOT,
|
|
||||||
"KILL": unix.SIGKILL,
|
|
||||||
"PIPE": unix.SIGPIPE,
|
|
||||||
"POLL": unix.SIGPOLL,
|
|
||||||
"PROF": unix.SIGPROF,
|
|
||||||
"PWR": unix.SIGPWR,
|
|
||||||
"QUIT": unix.SIGQUIT,
|
|
||||||
"SEGV": unix.SIGSEGV,
|
|
||||||
"STKFLT": unix.SIGSTKFLT,
|
|
||||||
"STOP": unix.SIGSTOP,
|
|
||||||
"SYS": unix.SIGSYS,
|
|
||||||
"TERM": unix.SIGTERM,
|
|
||||||
"TRAP": unix.SIGTRAP,
|
|
||||||
"TSTP": unix.SIGTSTP,
|
|
||||||
"TTIN": unix.SIGTTIN,
|
|
||||||
"TTOU": unix.SIGTTOU,
|
|
||||||
"URG": unix.SIGURG,
|
|
||||||
"USR1": unix.SIGUSR1,
|
|
||||||
"USR2": unix.SIGUSR2,
|
|
||||||
"VTALRM": unix.SIGVTALRM,
|
|
||||||
"WINCH": unix.SIGWINCH,
|
|
||||||
"XCPU": unix.SIGXCPU,
|
|
||||||
"XFSZ": unix.SIGXFSZ,
|
|
||||||
"RTMIN": sigrtmin,
|
|
||||||
"RTMIN+1": sigrtmin + 1,
|
|
||||||
"RTMIN+2": sigrtmin + 2,
|
|
||||||
"RTMIN+3": sigrtmin + 3,
|
|
||||||
"RTMIN+4": sigrtmin + 4,
|
|
||||||
"RTMIN+5": sigrtmin + 5,
|
|
||||||
"RTMIN+6": sigrtmin + 6,
|
|
||||||
"RTMIN+7": sigrtmin + 7,
|
|
||||||
"RTMIN+8": sigrtmin + 8,
|
|
||||||
"RTMIN+9": sigrtmin + 9,
|
|
||||||
"RTMIN+10": sigrtmin + 10,
|
|
||||||
"RTMIN+11": sigrtmin + 11,
|
|
||||||
"RTMIN+12": sigrtmin + 12,
|
|
||||||
"RTMIN+13": sigrtmin + 13,
|
|
||||||
"RTMIN+14": sigrtmin + 14,
|
|
||||||
"RTMIN+15": sigrtmin + 15,
|
|
||||||
"RTMAX-14": sigrtmax - 14,
|
|
||||||
"RTMAX-13": sigrtmax - 13,
|
|
||||||
"RTMAX-12": sigrtmax - 12,
|
|
||||||
"RTMAX-11": sigrtmax - 11,
|
|
||||||
"RTMAX-10": sigrtmax - 10,
|
|
||||||
"RTMAX-9": sigrtmax - 9,
|
|
||||||
"RTMAX-8": sigrtmax - 8,
|
|
||||||
"RTMAX-7": sigrtmax - 7,
|
|
||||||
"RTMAX-6": sigrtmax - 6,
|
|
||||||
"RTMAX-5": sigrtmax - 5,
|
|
||||||
"RTMAX-4": sigrtmax - 4,
|
|
||||||
"RTMAX-3": sigrtmax - 3,
|
|
||||||
"RTMAX-2": sigrtmax - 2,
|
|
||||||
"RTMAX-1": sigrtmax - 1,
|
|
||||||
"RTMAX": sigrtmax,
|
|
||||||
}
|
|
42
vendor/github.com/docker/docker/pkg/signal/signal_solaris.go
generated
vendored
42
vendor/github.com/docker/docker/pkg/signal/signal_solaris.go
generated
vendored
@ -1,42 +0,0 @@
|
|||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is a map of Solaris signals.
|
|
||||||
// SIGINFO and SIGTHR not defined for Solaris
|
|
||||||
var SignalMap = map[string]syscall.Signal{
|
|
||||||
"ABRT": syscall.SIGABRT,
|
|
||||||
"ALRM": syscall.SIGALRM,
|
|
||||||
"BUF": syscall.SIGBUS,
|
|
||||||
"CHLD": syscall.SIGCHLD,
|
|
||||||
"CONT": syscall.SIGCONT,
|
|
||||||
"EMT": syscall.SIGEMT,
|
|
||||||
"FPE": syscall.SIGFPE,
|
|
||||||
"HUP": syscall.SIGHUP,
|
|
||||||
"ILL": syscall.SIGILL,
|
|
||||||
"INT": syscall.SIGINT,
|
|
||||||
"IO": syscall.SIGIO,
|
|
||||||
"IOT": syscall.SIGIOT,
|
|
||||||
"KILL": syscall.SIGKILL,
|
|
||||||
"LWP": syscall.SIGLWP,
|
|
||||||
"PIPE": syscall.SIGPIPE,
|
|
||||||
"PROF": syscall.SIGPROF,
|
|
||||||
"QUIT": syscall.SIGQUIT,
|
|
||||||
"SEGV": syscall.SIGSEGV,
|
|
||||||
"STOP": syscall.SIGSTOP,
|
|
||||||
"SYS": syscall.SIGSYS,
|
|
||||||
"TERM": syscall.SIGTERM,
|
|
||||||
"TRAP": syscall.SIGTRAP,
|
|
||||||
"TSTP": syscall.SIGTSTP,
|
|
||||||
"TTIN": syscall.SIGTTIN,
|
|
||||||
"TTOU": syscall.SIGTTOU,
|
|
||||||
"URG": syscall.SIGURG,
|
|
||||||
"USR1": syscall.SIGUSR1,
|
|
||||||
"USR2": syscall.SIGUSR2,
|
|
||||||
"VTALRM": syscall.SIGVTALRM,
|
|
||||||
"WINCH": syscall.SIGWINCH,
|
|
||||||
"XCPU": syscall.SIGXCPU,
|
|
||||||
"XFSZ": syscall.SIGXFSZ,
|
|
||||||
}
|
|
21
vendor/github.com/docker/docker/pkg/signal/signal_unix.go
generated
vendored
21
vendor/github.com/docker/docker/pkg/signal/signal_unix.go
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Signals used in cli/command (no windows equivalent, use
|
|
||||||
// invalid signals so they don't get handled)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// SIGCHLD is a signal sent to a process when a child process terminates, is interrupted, or resumes after being interrupted.
|
|
||||||
SIGCHLD = syscall.SIGCHLD
|
|
||||||
// SIGWINCH is a signal sent to a process when its controlling terminal changes its size
|
|
||||||
SIGWINCH = syscall.SIGWINCH
|
|
||||||
// SIGPIPE is a signal sent to a process when a pipe is written to before the other end is open for reading
|
|
||||||
SIGPIPE = syscall.SIGPIPE
|
|
||||||
// DefaultStopSignal is the syscall signal used to stop a container in unix systems.
|
|
||||||
DefaultStopSignal = "SIGTERM"
|
|
||||||
)
|
|
10
vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go
generated
vendored
10
vendor/github.com/docker/docker/pkg/signal/signal_unsupported.go
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
// +build !linux,!darwin,!freebsd,!windows,!solaris
|
|
||||||
|
|
||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is an empty map of signals for unsupported platform.
|
|
||||||
var SignalMap = map[string]syscall.Signal{}
|
|
28
vendor/github.com/docker/docker/pkg/signal/signal_windows.go
generated
vendored
28
vendor/github.com/docker/docker/pkg/signal/signal_windows.go
generated
vendored
@ -1,28 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Signals used in cli/command (no windows equivalent, use
|
|
||||||
// invalid signals so they don't get handled)
|
|
||||||
const (
|
|
||||||
SIGCHLD = syscall.Signal(0xff)
|
|
||||||
SIGWINCH = syscall.Signal(0xff)
|
|
||||||
SIGPIPE = syscall.Signal(0xff)
|
|
||||||
// DefaultStopSignal is the syscall signal used to stop a container in windows systems.
|
|
||||||
DefaultStopSignal = "15"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SignalMap is a map of "supported" signals. As per the comment in GOLang's
|
|
||||||
// ztypes_windows.go: "More invented values for signals". Windows doesn't
|
|
||||||
// really support signals in any way, shape or form that Unix does.
|
|
||||||
//
|
|
||||||
// We have these so that docker kill can be used to gracefully (TERM) and
|
|
||||||
// forcibly (KILL) terminate a container on Windows.
|
|
||||||
var SignalMap = map[string]syscall.Signal{
|
|
||||||
"KILL": syscall.SIGKILL,
|
|
||||||
"TERM": syscall.SIGTERM,
|
|
||||||
}
|
|
104
vendor/github.com/docker/docker/pkg/signal/trap.go
generated
vendored
104
vendor/github.com/docker/docker/pkg/signal/trap.go
generated
vendored
@ -1,104 +0,0 @@
|
|||||||
package signal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
gosignal "os/signal"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Trap sets up a simplified signal "trap", appropriate for common
|
|
||||||
// behavior expected from a vanilla unix command-line tool in general
|
|
||||||
// (and the Docker engine in particular).
|
|
||||||
//
|
|
||||||
// * If SIGINT or SIGTERM are received, `cleanup` is called, then the process is terminated.
|
|
||||||
// * If SIGINT or SIGTERM are received 3 times before cleanup is complete, then cleanup is
|
|
||||||
// skipped and the process is terminated immediately (allows force quit of stuck daemon)
|
|
||||||
// * A SIGQUIT always causes an exit without cleanup, with a goroutine dump preceding exit.
|
|
||||||
// * Ignore SIGPIPE events. These are generated by systemd when journald is restarted while
|
|
||||||
// the docker daemon is not restarted and also running under systemd.
|
|
||||||
// Fixes https://github.com/docker/docker/issues/19728
|
|
||||||
//
|
|
||||||
func Trap(cleanup func(), logger interface {
|
|
||||||
Info(args ...interface{})
|
|
||||||
}) {
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
// we will handle INT, TERM, QUIT, SIGPIPE here
|
|
||||||
signals := []os.Signal{os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGPIPE}
|
|
||||||
gosignal.Notify(c, signals...)
|
|
||||||
go func() {
|
|
||||||
interruptCount := uint32(0)
|
|
||||||
for sig := range c {
|
|
||||||
if sig == syscall.SIGPIPE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(sig os.Signal) {
|
|
||||||
logger.Info(fmt.Sprintf("Processing signal '%v'", sig))
|
|
||||||
switch sig {
|
|
||||||
case os.Interrupt, syscall.SIGTERM:
|
|
||||||
if atomic.LoadUint32(&interruptCount) < 3 {
|
|
||||||
// Initiate the cleanup only once
|
|
||||||
if atomic.AddUint32(&interruptCount, 1) == 1 {
|
|
||||||
// Call the provided cleanup handler
|
|
||||||
cleanup()
|
|
||||||
os.Exit(0)
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 3 SIGTERM/INT signals received; force exit without cleanup
|
|
||||||
logger.Info("Forcing docker daemon shutdown without cleanup; 3 interrupts received")
|
|
||||||
}
|
|
||||||
case syscall.SIGQUIT:
|
|
||||||
DumpStacks("")
|
|
||||||
logger.Info("Forcing docker daemon shutdown without cleanup on SIGQUIT")
|
|
||||||
}
|
|
||||||
//for the SIGINT/TERM, and SIGQUIT non-clean shutdown case, exit with 128 + signal #
|
|
||||||
os.Exit(128 + int(sig.(syscall.Signal)))
|
|
||||||
}(sig)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
const stacksLogNameTemplate = "goroutine-stacks-%s.log"
|
|
||||||
|
|
||||||
// DumpStacks appends the runtime stack into file in dir and returns full path
|
|
||||||
// to that file.
|
|
||||||
func DumpStacks(dir string) (string, error) {
|
|
||||||
var (
|
|
||||||
buf []byte
|
|
||||||
stackSize int
|
|
||||||
)
|
|
||||||
bufferLen := 16384
|
|
||||||
for stackSize == len(buf) {
|
|
||||||
buf = make([]byte, bufferLen)
|
|
||||||
stackSize = runtime.Stack(buf, true)
|
|
||||||
bufferLen *= 2
|
|
||||||
}
|
|
||||||
buf = buf[:stackSize]
|
|
||||||
var f *os.File
|
|
||||||
if dir != "" {
|
|
||||||
path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.Replace(time.Now().Format(time.RFC3339), ":", "", -1)))
|
|
||||||
var err error
|
|
||||||
f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to open file to write the goroutine stacks")
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
defer f.Sync()
|
|
||||||
} else {
|
|
||||||
f = os.Stderr
|
|
||||||
}
|
|
||||||
if _, err := f.Write(buf); err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to write goroutine stacks")
|
|
||||||
}
|
|
||||||
return f.Name(), nil
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user