X Tutup
Skip to content

Commit b044ff0

Browse files
John Howardcrosbymichael
authored andcommitted
Refactor process.go for platform specific
Signed-off-by: John Howard <jhoward@microsoft.com> Move process sorter to new file Signed-off-by: Michael Crosby <crosbymichael@gmail.com> Sort containers by id This will not be the most accurate sorting but atleast the list will be consistent inbetween calls. Signed-off-by: Michael Crosby <crosbymichael@gmail.com> Allow runtime to be configurable via daemon start This allows people to pass an alternate name or location to the runtime binary to start containers. Signed-off-by: Michael Crosby <crosbymichael@gmail.com> Fix state output for containers Return the proper state/status for a container by checking if the pid is still alive. Also fix the cleanup handling in the shim to make sure containers are not left behind. Signed-off-by: Michael Crosby <crosbymichael@gmail.com> Properly wait for container start Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
1 parent 0ad7654 commit b044ff0

File tree

19 files changed

+323
-206
lines changed

19 files changed

+323
-206
lines changed

api/grpc/server/server.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ func createAPIContainer(c runtime.Container, getPids bool) (*types.Container, er
144144
procs = append(procs, appendToProcs)
145145
}
146146
var pids []int
147-
if getPids {
147+
state := c.State()
148+
if getPids && (state == runtime.Running || state == runtime.Paused) {
148149
if pids, err = c.Pids(); err != nil {
149150
return nil, grpc.Errorf(codes.Internal, "get all pids for container")
150151
}
@@ -154,8 +155,9 @@ func createAPIContainer(c runtime.Container, getPids bool) (*types.Container, er
154155
BundlePath: c.Path(),
155156
Processes: procs,
156157
Labels: c.Labels(),
157-
Status: string(c.State()),
158+
Status: string(state),
158159
Pids: toUint32(pids),
160+
Runtime: c.Runtime(),
159161
}, nil
160162
}
161163

api/grpc/types/api.pb.go

Lines changed: 99 additions & 118 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/grpc/types/api.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ message Container {
132132
string status = 4; // Container status ("running", "paused", etc.)
133133
repeated string labels = 5;
134134
repeated uint32 pids = 6;
135+
string runtime = 7; // runtime used to execute the container
135136
}
136137

137138
// Machine is information about machine on which containerd is run

containerd-shim/main.go

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,62 @@ import (
1212
"github.com/docker/docker/pkg/term"
1313
)
1414

15+
var runtimeLog string
16+
1517
func setupLogger() {
1618
f, err := os.OpenFile("/tmp/shim.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755)
1719
if err != nil {
1820
panic(err)
1921
}
2022
logrus.SetOutput(f)
23+
runtimeLog = "/tmp/runtime.log"
2124
}
2225

23-
// containerd-shim is a small shim that sits in front of a runc implementation
26+
// containerd-shim is a small shim that sits in front of a runtime implementation
2427
// that allows it to be repartented to init and handle reattach from the caller.
2528
//
2629
// the cwd of the shim should be the bundle for the container. Arg1 should be the path
2730
// to the state directory where the shim can locate fifos and other information.
2831
func main() {
2932
flag.Parse()
3033
// start handling signals as soon as possible so that things are properly reaped
31-
// or if runc exits before we hit the handler
34+
// or if runtime exits before we hit the handler
3235
signals := make(chan os.Signal, 2048)
3336
signal.Notify(signals)
3437
// set the shim as the subreaper for all orphaned processes created by the container
3538
if err := osutils.SetSubreaper(1); err != nil {
36-
logrus.WithField("error", err).Fatal("shim: set as subreaper")
39+
logrus.WithField("error", err).Error("shim: set as subreaper")
40+
return
3741
}
3842
// open the exit pipe
3943
f, err := os.OpenFile("exit", syscall.O_WRONLY, 0)
4044
if err != nil {
41-
logrus.WithField("error", err).Fatal("shim: open exit pipe")
45+
logrus.WithField("error", err).Error("shim: open exit pipe")
46+
return
4247
}
4348
defer f.Close()
4449
control, err := os.OpenFile("control", syscall.O_RDWR, 0)
4550
if err != nil {
46-
logrus.WithField("error", err).Fatal("shim: open control pipe")
51+
logrus.WithField("error", err).Error("shim: open control pipe")
52+
return
4753
}
4854
defer control.Close()
49-
p, err := newProcess(flag.Arg(0), flag.Arg(1))
55+
p, err := newProcess(flag.Arg(0), flag.Arg(1), flag.Arg(2))
5056
if err != nil {
51-
logrus.WithField("error", err).Fatal("shim: create new process")
57+
logrus.WithField("error", err).Error("shim: create new process")
58+
return
5259
}
60+
defer func() {
61+
if err := p.Close(); err != nil {
62+
logrus.WithField("error", err).Error("shim: close stdio")
63+
}
64+
if err := p.delete(); err != nil {
65+
logrus.WithField("error", err).Error("shim: delete runtime state")
66+
}
67+
}()
5368
if err := p.start(); err != nil {
54-
p.delete()
55-
logrus.WithField("error", err).Fatal("shim: start process")
69+
logrus.WithField("error", err).Error("shim: start process")
70+
return
5671
}
5772
go func() {
5873
for {
@@ -87,13 +102,13 @@ func main() {
87102
logrus.WithField("error", err).Error("shim: reaping child processes")
88103
}
89104
for _, e := range exits {
90-
// check to see if runc is one of the processes that has exited
105+
// check to see if runtime is one of the processes that has exited
91106
if e.Pid == p.pid() {
92107
exitShim = true
93108
logrus.WithFields(logrus.Fields{
94109
"pid": e.Pid,
95110
"status": e.Status,
96-
}).Info("shim: runc exited")
111+
}).Info("shim: runtime exited")
97112
if err := writeInt("exitStatus", e.Status); err != nil {
98113
logrus.WithFields(logrus.Fields{
99114
"error": err,
@@ -103,14 +118,8 @@ func main() {
103118
}
104119
}
105120
}
106-
// runc has exited so the shim can also exit
121+
// runtime has exited so the shim can also exit
107122
if exitShim {
108-
if err := p.Close(); err != nil {
109-
logrus.WithField("error", err).Error("shim: close stdio")
110-
}
111-
if err := p.delete(); err != nil {
112-
logrus.WithField("error", err).Error("shim: delete runc state")
113-
}
114123
return
115124
}
116125
}

containerd-shim/process.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"io"
67
"io/ioutil"
78
"os"
@@ -25,12 +26,14 @@ type process struct {
2526
console libcontainer.Console
2627
consolePath string
2728
state *runtime.ProcessState
29+
runtime string
2830
}
2931

30-
func newProcess(id, bundle string) (*process, error) {
32+
func newProcess(id, bundle, runtimeName string) (*process, error) {
3133
p := &process{
32-
id: id,
33-
bundle: bundle,
34+
id: id,
35+
bundle: bundle,
36+
runtime: runtimeName,
3437
}
3538
s, err := loadProcess()
3639
if err != nil {
@@ -81,7 +84,7 @@ func (p *process) start() error {
8184
if err != nil {
8285
return err
8386
}
84-
args := []string{}
87+
args := []string{"--log", runtimeLog}
8588
if p.state.Exec {
8689
args = append(args, "exec",
8790
"--process", filepath.Join(cwd, "process.json"),
@@ -114,7 +117,7 @@ func (p *process) start() error {
114117
"--pid-file", filepath.Join(cwd, "pid"),
115118
p.id,
116119
)
117-
cmd := exec.Command("runc", args...)
120+
cmd := exec.Command(p.runtime, args...)
118121
cmd.Dir = p.bundle
119122
cmd.Stdin = p.stdio.stdin
120123
cmd.Stdout = p.stdio.stdout
@@ -146,7 +149,10 @@ func (p *process) pid() int {
146149

147150
func (p *process) delete() error {
148151
if !p.state.Exec {
149-
return exec.Command("runc", "delete", p.id).Run()
152+
out, err := exec.Command(p.runtime, "delete", p.id).CombinedOutput()
153+
if err != nil {
154+
return fmt.Errorf("%s: %v", out, err)
155+
}
150156
}
151157
return nil
152158
}

containerd/main.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ var daemonFlags = []cli.Flag{
4141
Value: defaultGRPCEndpoint,
4242
Usage: "Address on which GRPC API will listen",
4343
},
44+
cli.StringFlag{
45+
Name: "runtime,r",
46+
Value: "runc",
47+
Usage: "name of the OCI compliant runtime to use when executing containers",
48+
},
4449
}
4550

4651
func main() {
@@ -58,6 +63,7 @@ func main() {
5863
context.String("state-dir"),
5964
10,
6065
context.Bool("oom-notify"), // TODO Windows: Remove oom-notify
66+
context.String("runtime"),
6167
); err != nil {
6268
logrus.Fatal(err)
6369
}
@@ -67,11 +73,11 @@ func main() {
6773
}
6874
}
6975

70-
func daemon(address, stateDir string, concurrency int, oom bool) error {
76+
func daemon(address, stateDir string, concurrency int, oom bool, runtimeName string) error {
7177
// setup a standard reaper so that we don't leave any zombies if we are still alive
7278
// this is just good practice because we are spawning new processes
7379
go reapProcesses()
74-
sv, err := supervisor.New(stateDir, oom)
80+
sv, err := supervisor.New(stateDir, oom, runtimeName)
7581
if err != nil {
7682
return err
7783
}

ctr/container.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ func listContainers(context *cli.Context) {
9292
}
9393
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
9494
fmt.Fprint(w, "ID\tPATH\tSTATUS\tPROCESSES\n")
95+
sortContainers(resp.Containers)
9596
for _, c := range resp.Containers {
9697
procs := []string{}
9798
for _, p := range c.Processes {

ctr/sort.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"sort"
5+
6+
"github.com/docker/containerd/api/grpc/types"
7+
)
8+
9+
func sortContainers(c []*types.Container) {
10+
sort.Sort(&containerSorter{c})
11+
}
12+
13+
type containerSorter struct {
14+
c []*types.Container
15+
}
16+
17+
func (s *containerSorter) Len() int {
18+
return len(s.c)
19+
}
20+
21+
func (s *containerSorter) Swap(i, j int) {
22+
s.c[i], s.c[j] = s.c[j], s.c[i]
23+
}
24+
25+
func (s *containerSorter) Less(i, j int) bool {
26+
return s.c[i].Id < s.c[j].Id
27+
}

runtime/container.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io/ioutil"
66
"os"
77
"path/filepath"
8+
"syscall"
89

910
"github.com/Sirupsen/logrus"
1011
)
@@ -42,6 +43,8 @@ type Container interface {
4243
Pids() ([]int, error)
4344
// Stats returns realtime container stats and resource information
4445
Stats() (*Stat, error)
46+
// Name or path of the OCI compliant runtime used to execute the container
47+
Runtime() string
4548
// OOM signals the channel if the container received an OOM notification
4649
// OOM() (<-chan struct{}, error)
4750
}
@@ -68,13 +71,14 @@ func NewStdio(stdin, stdout, stderr string) Stdio {
6871
}
6972

7073
// New returns a new container
71-
func New(root, id, bundle string, labels []string) (Container, error) {
74+
func New(root, id, bundle, runtimeName string, labels []string) (Container, error) {
7275
c := &container{
7376
root: root,
7477
id: id,
7578
bundle: bundle,
7679
labels: labels,
7780
processes: make(map[string]*process),
81+
runtime: runtimeName,
7882
}
7983
if err := os.Mkdir(filepath.Join(root, id), 0755); err != nil {
8084
return nil, err
@@ -85,8 +89,9 @@ func New(root, id, bundle string, labels []string) (Container, error) {
8589
}
8690
defer f.Close()
8791
if err := json.NewEncoder(f).Encode(state{
88-
Bundle: bundle,
89-
Labels: labels,
92+
Bundle: bundle,
93+
Labels: labels,
94+
Runtime: runtimeName,
9095
}); err != nil {
9196
return nil, err
9297
}
@@ -108,6 +113,7 @@ func Load(root, id string) (Container, error) {
108113
id: id,
109114
bundle: s.Bundle,
110115
labels: s.Labels,
116+
runtime: s.Runtime,
111117
processes: make(map[string]*process),
112118
}
113119
dirs, err := ioutil.ReadDir(filepath.Join(root, id))
@@ -151,6 +157,7 @@ type container struct {
151157
root string
152158
id string
153159
bundle string
160+
runtime string
154161
processes map[string]*process
155162
stdio Stdio
156163
labels []string
@@ -182,6 +189,14 @@ func (c *container) readSpec() (*PlatformSpec, error) {
182189
}
183190

184191
func (c *container) State() State {
192+
proc := c.processes["init"]
193+
if proc == nil || proc.pid == 0 {
194+
return Stopped
195+
}
196+
err := syscall.Kill(proc.pid, 0)
197+
if err != nil && err == syscall.ESRCH {
198+
return Stopped
199+
}
185200
return Running
186201
}
187202

0 commit comments

Comments
 (0)
X Tutup