mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
4776b4326a
To make the code cleaner, and more clear, refactor the syncT handling used when creating the `runc init` process. In addition, document the state changes so that people actually understand what is going on. Rather than only using syncT for the standard initProcess, use it for both initProcess and setnsProcess. This removes some special cases, as well as allowing for the use of syncT with setnsProcess. Also remove a bunch of the boilerplate around syncT handling. This patch is part of the console rewrite patchset. Signed-off-by: Aleksa Sarai <asarai@suse.de>
103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
package libcontainer
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/utils"
|
|
)
|
|
|
|
type syncType uint8
|
|
|
|
// Constants that are used for synchronisation between the parent and child
|
|
// during container setup. They come in pairs (with procError being a generic
|
|
// response which is followed by a &genericError).
|
|
//
|
|
// [ child ] <-> [ parent ]
|
|
//
|
|
// procHooks --> [run hooks]
|
|
// <-- procResume
|
|
//
|
|
// procReady --> [final setup]
|
|
// <-- procRun
|
|
const (
|
|
procError syncType = iota
|
|
procReady
|
|
procRun
|
|
procHooks
|
|
procResume
|
|
)
|
|
|
|
type syncT struct {
|
|
Type syncType `json:"type"`
|
|
}
|
|
|
|
// writeSync is used to write to a synchronisation pipe. An error is returned
|
|
// if there was a problem writing the payload.
|
|
func writeSync(pipe io.Writer, sync syncType) error {
|
|
if err := utils.WriteJSON(pipe, syncT{sync}); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// readSync is used to read from a synchronisation pipe. An error is returned
|
|
// if we got a genericError, the pipe was closed, or we got an unexpected flag.
|
|
func readSync(pipe io.Reader, expected syncType) error {
|
|
var procSync syncT
|
|
if err := json.NewDecoder(pipe).Decode(&procSync); err != nil {
|
|
if err == io.EOF {
|
|
return fmt.Errorf("parent closed synchronisation channel")
|
|
}
|
|
|
|
if procSync.Type == procError {
|
|
var ierr genericError
|
|
|
|
if err := json.NewDecoder(pipe).Decode(&ierr); err != nil {
|
|
return fmt.Errorf("failed reading error from parent: %v", err)
|
|
}
|
|
|
|
return &ierr
|
|
}
|
|
|
|
if procSync.Type != expected {
|
|
return fmt.Errorf("invalid synchronisation flag from parent")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// parseSync runs the given callback function on each syncT received from the
|
|
// child. It will return once io.EOF is returned from the given pipe.
|
|
func parseSync(pipe io.Reader, fn func(*syncT) error) error {
|
|
dec := json.NewDecoder(pipe)
|
|
for {
|
|
var sync syncT
|
|
if err := dec.Decode(&sync); err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return err
|
|
}
|
|
|
|
// We handle this case outside fn for cleanliness reasons.
|
|
var ierr *genericError
|
|
if sync.Type == procError {
|
|
if err := dec.Decode(&ierr); err != nil && err != io.EOF {
|
|
return newSystemErrorWithCause(err, "decoding proc error from init")
|
|
}
|
|
if ierr != nil {
|
|
return ierr
|
|
}
|
|
// Programmer error.
|
|
panic("No error following JSON procError payload.")
|
|
}
|
|
|
|
if err := fn(&sync); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|