Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit f67692f

Browse files
authored
Merge pull request #519 from WeiZhang555/guarantee-logs
Don't call os.Exit explicitly to avoid lost of logs
2 parents c8033af + a1cb915 commit f67692f

File tree

9 files changed

+155
-147
lines changed

9 files changed

+155
-147
lines changed

containerd/containerd.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ var ContainerdCommand = cli.Command{
7676
return nil
7777
},
7878

79-
Action: func(context *cli.Context) {
79+
Action: func(context *cli.Context) error {
8080
driver := context.GlobalString("driver")
8181
kernel := context.GlobalString("kernel")
8282
initrd := context.GlobalString("initrd")
@@ -95,13 +95,15 @@ var ContainerdCommand = cli.Command{
9595
path := filepath.Join(template, "config.json")
9696
f, err := os.Open(path)
9797
if err != nil {
98-
glog.Errorf("open template JSON configuration file failed: %v", err)
99-
os.Exit(-1)
98+
err = fmt.Errorf("open template JSON configuration file failed: %v", err)
99+
glog.Error(err)
100+
return cli.NewExitError(err.Error(), -1)
100101
}
101102
if err := json.NewDecoder(f).Decode(&tconfig); err != nil {
102-
glog.Errorf("parse template JSON configuration file failed: %v", err)
103+
err = fmt.Errorf("parse template JSON configuration file failed: %v", err)
104+
glog.Error(err)
103105
f.Close()
104-
os.Exit(-1)
106+
return cli.NewExitError(err.Error(), -1)
105107
}
106108
f.Close()
107109

@@ -116,15 +118,16 @@ var ContainerdCommand = cli.Command{
116118
driver = tconfig.Driver
117119
}
118120
} else if (bios == "" || cbfs == "") && (kernel == "" || initrd == "") {
119-
glog.Error("argument kernel+initrd or bios+cbfs must be set")
120-
os.Exit(1)
121+
err := fmt.Errorf("argument kernel+initrd or bios+cbfs must be set")
122+
glog.Error(err)
123+
return cli.NewExitError(err.Error(), -1)
121124
}
122125

123126
hypervisor.InterfaceCount = 0
124127
var err error
125128
if hypervisor.HDriver, err = driverloader.Probe(driver); err != nil {
126129
glog.Errorf("%v", err)
127-
os.Exit(1)
130+
return cli.NewExitError(err.Error(), -1)
128131
}
129132

130133
var f factory.Factory
@@ -144,7 +147,7 @@ var ContainerdCommand = cli.Command{
144147
context.GlobalInt("default_cpus"), context.GlobalInt("default_memory"))
145148
if err != nil {
146149
glog.Errorf("%v", err)
147-
os.Exit(1)
150+
return cli.NewExitError(err.Error(), -1)
148151
}
149152

150153
if context.Bool("solo-namespaced") {
@@ -153,12 +156,13 @@ var ContainerdCommand = cli.Command{
153156

154157
if err = daemon(sv, context.String("listen")); err != nil {
155158
glog.Errorf("%v", err)
156-
os.Exit(1)
159+
return cli.NewExitError(err.Error(), -1)
157160
}
158161

159162
if context.Bool("solo-namespaced") {
160163
os.RemoveAll(containerdDir)
161164
}
165+
return nil
162166
},
163167
}
164168

create.go

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -57,39 +57,39 @@ command(s) that get executed on start, edit the args parameter of the spec. See
5757
Usage: "[ignore on runv] do not use pivot root to jail process inside rootfs. This should be used whenever the rootfs is on top of a ramdisk",
5858
},
5959
},
60-
Action: func(context *cli.Context) {
61-
runContainer(context, true)
60+
Action: func(context *cli.Context) error {
61+
if err := runContainer(context, true); err != nil {
62+
return cli.NewExitError(fmt.Sprintf("Run Container error: %v", err), -1)
63+
}
64+
return nil
6265
},
6366
}
6467

65-
func runContainer(context *cli.Context, createOnly bool) {
68+
func runContainer(context *cli.Context, createOnly bool) error {
6669
root := context.GlobalString("root")
6770
bundle := context.String("bundle")
6871
container := context.Args().First()
6972
ocffile := filepath.Join(bundle, specConfig)
7073
spec, err := loadSpec(ocffile)
7174
if err != nil {
72-
fmt.Fprintf(os.Stderr, "load config failed: %v\n", err)
73-
os.Exit(-1)
75+
return fmt.Errorf("load config failed: %v", err)
7476
}
7577
if spec.Linux == nil {
76-
fmt.Fprintf(os.Stderr, "it is not linux container config\n")
77-
os.Exit(-1)
78+
return fmt.Errorf("it is not linux container config")
7879
}
7980
if os.Geteuid() != 0 {
80-
fmt.Fprintf(os.Stderr, "runv should be run as root\n")
81-
os.Exit(-1)
81+
return fmt.Errorf("runv should be run as root")
8282
}
8383
if container == "" {
84-
fmt.Fprintf(os.Stderr, "no container id provided\n")
85-
os.Exit(-1)
84+
return fmt.Errorf("no container id provided")
8685
}
8786
_, err = os.Stat(filepath.Join(root, container))
8887
if err == nil {
89-
fmt.Fprintf(os.Stderr, "Container %q exists\n", container)
90-
os.Exit(-1)
88+
return fmt.Errorf("container %q exists", container)
89+
}
90+
if err = checkConsole(context, &spec.Process, createOnly); err != nil {
91+
return err
9192
}
92-
checkConsole(context, &spec.Process, createOnly)
9393

9494
var sharedContainer string
9595
if containerType, ok := spec.Annotations["ocid/container_type"]; ok {
@@ -100,24 +100,20 @@ func runContainer(context *cli.Context, createOnly bool) {
100100
for _, ns := range spec.Linux.Namespaces {
101101
if ns.Path != "" {
102102
if strings.Contains(ns.Path, "/") {
103-
fmt.Fprintf(os.Stderr, "Runv doesn't support path to namespace file, it supports containers name as shared namespaces only\n")
104-
os.Exit(-1)
103+
return fmt.Errorf("Runv doesn't support path to namespace file, it supports containers name as shared namespaces only")
105104
}
106105
if ns.Type == "mount" {
107106
// TODO support it!
108-
fmt.Fprintf(os.Stderr, "Runv doesn't support shared mount namespace currently\n")
109-
os.Exit(-1)
107+
return fmt.Errorf("Runv doesn't support shared mount namespace currently")
110108
}
111109
sharedContainer = ns.Path
112110
_, err = os.Stat(filepath.Join(root, sharedContainer, stateJson))
113111
if err != nil {
114-
fmt.Fprintf(os.Stderr, "The container %q is not existing or not ready\n", sharedContainer)
115-
os.Exit(-1)
112+
return fmt.Errorf("The container %q is not existing or not ready", sharedContainer)
116113
}
117114
_, err = os.Stat(filepath.Join(root, sharedContainer, "namespace"))
118115
if err != nil {
119-
fmt.Fprintf(os.Stderr, "The container %q is not ready\n", sharedContainer)
120-
os.Exit(-1)
116+
return fmt.Errorf("The container %q is not ready", sharedContainer)
121117
}
122118
}
123119
}
@@ -129,26 +125,22 @@ func runContainer(context *cli.Context, createOnly bool) {
129125
namespace = filepath.Join(root, sharedContainer, "namespace")
130126
namespace, err = os.Readlink(namespace)
131127
if err != nil {
132-
fmt.Fprintf(os.Stderr, "Cannot get namespace link of the shared container: %v\n", err)
133-
os.Exit(-1)
128+
return fmt.Errorf("cannot get namespace link of the shared container: %v", err)
134129
}
135130
} else {
136131
path, err := osext.Executable()
137132
if err != nil {
138-
fmt.Fprintf(os.Stderr, "cannot find self executable path for %s: %v\n", os.Args[0], err)
139-
os.Exit(-1)
133+
return fmt.Errorf("cannot find self executable path for %s: %v", os.Args[0], err)
140134
}
141135

142136
kernel, initrd, bios, cbfs, err := getKernelFiles(context, spec.Root.Path)
143137
if err != nil {
144-
fmt.Fprintf(os.Stderr, "Can't find kernel/initrd/bios/cbfs files")
145-
os.Exit(-1)
138+
return fmt.Errorf("can't find kernel/initrd/bios/cbfs files")
146139
}
147140

148141
namespace, err = ioutil.TempDir("/run", "runv-namespace-")
149142
if err != nil {
150-
fmt.Fprintf(os.Stderr, "Failed to create runv namespace path: %v", err)
151-
os.Exit(-1)
143+
return fmt.Errorf("failed to create runv namespace path: %v", err)
152144
}
153145

154146
args := []string{
@@ -176,8 +168,7 @@ func runContainer(context *cli.Context, createOnly bool) {
176168
if context.GlobalIsSet(goption) {
177169
abs_path, err := filepath.Abs(context.GlobalString(goption))
178170
if err != nil {
179-
fmt.Fprintf(os.Stderr, "Cannot get abs path for %s: %v\n", goption, err)
180-
os.Exit(-1)
171+
return fmt.Errorf("Cannot get abs path for %s: %v\n", goption, err)
181172
}
182173
args = append(args, "--"+goption, abs_path)
183174
}
@@ -198,8 +189,7 @@ func runContainer(context *cli.Context, createOnly bool) {
198189
}
199190
err = cmd.Start()
200191
if err != nil {
201-
fmt.Fprintf(os.Stderr, "failed to launch runv containerd: %v\n", err)
202-
os.Exit(-1)
192+
return fmt.Errorf("failed to launch runv containerd: %v", err)
203193
}
204194
if _, err = os.Stat(filepath.Join(namespace, "namespaced.sock")); os.IsNotExist(err) {
205195
time.Sleep(3 * time.Second)
@@ -208,34 +198,31 @@ func runContainer(context *cli.Context, createOnly bool) {
208198

209199
err = createContainer(context, container, namespace, spec)
210200
if err != nil {
211-
fmt.Fprintf(os.Stderr, "error %v\n", err)
212201
cmd.Process.Signal(syscall.SIGINT)
213-
os.Exit(-1)
202+
return fmt.Errorf("failed to create container: %v", err)
214203
}
215204
if !createOnly {
216205
address := filepath.Join(namespace, "namespaced.sock")
217206
startContainer(context, bundle, container, address, spec, context.Bool("detach"))
218207
}
219-
os.Exit(0)
208+
return nil
220209
}
221210

222-
func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) {
211+
func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) error {
223212
if context.String("console") != "" && context.String("console-socket") != "" {
224-
fmt.Fprintf(os.Stderr, "only one of --console & --console-socket can be specified")
225-
os.Exit(-1)
213+
return fmt.Errorf("only one of --console & --console-socket can be specified")
226214
}
227215
detach := createOnly
228216
if !createOnly {
229217
detach = context.Bool("detach")
230218
}
231219
if (context.String("console") != "" || context.String("console-socket") != "") && !detach {
232-
fmt.Fprintf(os.Stderr, "--console[-socket] should be used on detached mode\n")
233-
os.Exit(-1)
220+
return fmt.Errorf("--console[-socket] should be used on detached mode\n")
234221
}
235222
if (context.String("console") != "" || context.String("console-socket") != "") && !p.Terminal {
236-
fmt.Fprintf(os.Stderr, "--console[-socket] should be used on tty mode\n")
237-
os.Exit(-1)
223+
return fmt.Errorf("--console[-socket] should be used on tty mode\n")
238224
}
225+
return nil
239226
}
240227

241228
// Shared namespaces multiple containers suppurt
@@ -253,7 +240,10 @@ func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) {
253240

254241
func createContainer(context *cli.Context, container, namespace string, config *specs.Spec) error {
255242
address := filepath.Join(namespace, "namespaced.sock")
256-
c := getClient(address)
243+
c, err := getClient(address)
244+
if err != nil {
245+
return err
246+
}
257247

258248
return ociCreate(context, container, func(stdin, stdout, stderr string) error {
259249
r := &types.CreateContainerRequest{
@@ -282,8 +272,7 @@ func createContainer(context *cli.Context, container, namespace string, config *
282272
func ociCreate(context *cli.Context, container string, createFunc func(stdin, stdout, stderr string) error) error {
283273
path, err := osext.Executable()
284274
if err != nil {
285-
fmt.Fprintf(os.Stderr, "cannot find self executable path for %s: %v\n", os.Args[0], err)
286-
os.Exit(-1)
275+
return fmt.Errorf("cannot find self executable path for %s: %v\n", os.Args[0], err)
287276
}
288277

289278
var stdin, stdout, stderr string

exec.go

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -85,44 +85,46 @@ following will output a list of processes running in the container:
8585
Usage: "[ignore on runv] disable the use of the subreaper used to reap reparented processes",
8686
},
8787
},
88-
Action: func(context *cli.Context) {
88+
Action: func(context *cli.Context) error {
8989
root := context.GlobalString("root")
9090
container := context.Args().First()
9191

9292
if container == "" {
93-
fmt.Printf("Please specify container ID\n")
94-
os.Exit(-1)
93+
return cli.NewExitError("Please specify container ID", -1)
9594
}
9695
if os.Geteuid() != 0 {
97-
fmt.Printf("runv should be run as root\n")
98-
os.Exit(-1)
96+
return cli.NewExitError("runv should be run as root", -1)
9997
}
10098

10199
// get bundle path from state
102100
path := filepath.Join(root, container, stateJson)
103101
f, err := os.Open(path)
104102
if err != nil {
105-
fmt.Printf("open JSON configuration file failed: %v\n", err)
106-
os.Exit(-1)
103+
return cli.NewExitError(fmt.Sprintf("open JSON configuration file failed: %v", err), -1)
107104
}
108105
defer f.Close()
109106
var s *specs.State
110107
if err := json.NewDecoder(f).Decode(&s); err != nil {
111-
fmt.Printf("parse JSON configuration file failed: %v\n", err)
112-
os.Exit(-1)
108+
return cli.NewExitError(fmt.Sprintf("parse JSON configuration file failed: %v", err), -1)
113109
}
114110
bundle := s.Bundle
115111

116112
// get process
117113
config, err := getProcess(context, bundle)
118114
if err != nil {
119-
fmt.Printf("get process config failed %v\n", err)
120-
os.Exit(-1)
115+
return cli.NewExitError(fmt.Sprintf("get process config failed %v", err), -1)
116+
}
117+
if err := checkConsole(context, config, false); err != nil {
118+
return cli.NewExitError(err.Error(), -1)
121119
}
122-
checkConsole(context, config, false)
123120

124-
code := runProcess(context, container, config)
125-
os.Exit(code)
121+
code, err := runProcess(context, container, config)
122+
if code != 0 {
123+
return cli.NewExitError(err, code)
124+
} else if err != nil {
125+
return cli.NewExitError(err, -1)
126+
}
127+
return nil
126128
},
127129
}
128130

@@ -188,23 +190,25 @@ func getProcess(context *cli.Context, bundle string) (*specs.Process, error) {
188190
return &p, nil
189191
}
190192

191-
func runProcess(context *cli.Context, container string, config *specs.Process) int {
193+
func runProcess(context *cli.Context, container string, config *specs.Process) (int, error) {
192194
pid := os.Getpid()
193195
process := fmt.Sprintf("p-%x", pid+0xabcdef) // uniq name
194-
c := getClient(filepath.Join(context.GlobalString("root"), container, "namespace/namespaced.sock"))
196+
c, err := getClient(filepath.Join(context.GlobalString("root"), container, "namespace/namespaced.sock"))
197+
if err != nil {
198+
return -1, fmt.Errorf("failed to get client: %v", err)
199+
}
195200
evChan := containerEvents(c, container)
196201

197202
if !context.Bool("detach") && config.Terminal {
198203
s, err := term.SetRawTerminal(os.Stdin.Fd())
199204
if err != nil {
200-
fmt.Printf("error %v\n", err)
201-
return -1
205+
return -1, fmt.Errorf("failed to set raw terminal: %v", err)
202206
}
203207
defer term.RestoreTerminal(os.Stdin.Fd(), s)
204208
monitorTtySize(c, container, process)
205209
}
206210

207-
err := ociCreate(context, container, func(stdin, stdout, stderr string) error {
211+
err = ociCreate(context, container, func(stdin, stdout, stderr string) error {
208212
p := &types.AddProcessRequest{
209213
Id: container,
210214
Pid: process,
@@ -226,16 +230,16 @@ func runProcess(context *cli.Context, container string, config *specs.Process) i
226230
return nil
227231
})
228232
if err != nil {
229-
return -1
233+
return -1, err
230234
}
231235

232236
if !context.Bool("detach") {
233237
for e := range evChan {
234238
if e.Type == "exit" && e.Pid == process {
235-
return int(e.Status)
239+
return int(e.Status), nil
236240
}
237241
}
238-
return -1
242+
return -1, fmt.Errorf("unknown error")
239243
}
240-
return 0
244+
return 0, nil
241245
}

0 commit comments

Comments
 (0)