 cd72819b53
			
		
	
	cd72819b53
	
	
	
		
			
			To avoid buffer bloat in long running processes, we try to use buffer pools where possible. This is meant to address shim memory usage issues, but may not be the root cause. Signed-off-by: Stephen J Day <stephen.day@docker.com>
		
			
				
	
	
		
			89 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			89 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build !windows
 | |
| 
 | |
| package proc
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/containerd/containerd/errdefs"
 | |
| 	runc "github.com/containerd/go-runc"
 | |
| 	"github.com/pkg/errors"
 | |
| 	"golang.org/x/sys/unix"
 | |
| )
 | |
| 
 | |
| // TODO(mlaventure): move to runc package?
 | |
| func getLastRuntimeError(r *runc.Runc) (string, error) {
 | |
| 	if r.Log == "" {
 | |
| 		return "", nil
 | |
| 	}
 | |
| 
 | |
| 	f, err := os.OpenFile(r.Log, os.O_RDONLY, 0400)
 | |
| 	if err != nil {
 | |
| 		return "", err
 | |
| 	}
 | |
| 
 | |
| 	var (
 | |
| 		errMsg string
 | |
| 		log    struct {
 | |
| 			Level string
 | |
| 			Msg   string
 | |
| 			Time  time.Time
 | |
| 		}
 | |
| 	)
 | |
| 
 | |
| 	dec := json.NewDecoder(f)
 | |
| 	for err = nil; err == nil; {
 | |
| 		if err = dec.Decode(&log); err != nil && err != io.EOF {
 | |
| 			return "", err
 | |
| 		}
 | |
| 		if log.Level == "error" {
 | |
| 			errMsg = strings.TrimSpace(log.Msg)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return errMsg, nil
 | |
| }
 | |
| 
 | |
| // criuError returns only the first line of the error message from criu
 | |
| // it tries to add an invalid dump log location when returning the message
 | |
| func criuError(err error) string {
 | |
| 	parts := strings.Split(err.Error(), "\n")
 | |
| 	return parts[0]
 | |
| }
 | |
| 
 | |
| func copyFile(to, from string) error {
 | |
| 	ff, err := os.Open(from)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer ff.Close()
 | |
| 	tt, err := os.Create(to)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer tt.Close()
 | |
| 
 | |
| 	p := bufPool.Get().(*[]byte)
 | |
| 	defer bufPool.Put(p)
 | |
| 	_, err = io.CopyBuffer(tt, ff, *p)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| func checkKillError(err error) error {
 | |
| 	if err == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if strings.Contains(err.Error(), "os: process already finished") || err == unix.ESRCH {
 | |
| 		return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
 | |
| 	}
 | |
| 	return errors.Wrapf(err, "unknown error after kill")
 | |
| }
 | |
| 
 | |
| func hasNoIO(r *CreateConfig) bool {
 | |
| 	return r.Stdin == "" && r.Stdout == "" && r.Stderr == ""
 | |
| }
 |