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

Commit a1cb915

Browse files
committed
Don't call os.Exit explicitly to avoid lost of log
Do not call os.Exit directly in codes, but call "return cli.NewExitError" instead, so that after the program terminated, glog can flush and no logs will be lost. Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
1 parent dac6bdc commit a1cb915

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{
@@ -173,8 +165,7 @@ func runContainer(context *cli.Context, createOnly bool) {
173165
if context.GlobalIsSet(goption) {
174166
abs_path, err := filepath.Abs(context.GlobalString(goption))
175167
if err != nil {
176-
fmt.Fprintf(os.Stderr, "Cannot get abs path for %s: %v\n", goption, err)
177-
os.Exit(-1)
168+
return fmt.Errorf("Cannot get abs path for %s: %v\n", goption, err)
178169
}
179170
args = append(args, "--"+goption, abs_path)
180171
}
@@ -195,8 +186,7 @@ func runContainer(context *cli.Context, createOnly bool) {
195186
}
196187
err = cmd.Start()
197188
if err != nil {
198-
fmt.Fprintf(os.Stderr, "failed to launch runv containerd: %v\n", err)
199-
os.Exit(-1)
189+
return fmt.Errorf("failed to launch runv containerd: %v", err)
200190
}
201191
if _, err = os.Stat(filepath.Join(namespace, "namespaced.sock")); os.IsNotExist(err) {
202192
time.Sleep(3 * time.Second)
@@ -205,34 +195,31 @@ func runContainer(context *cli.Context, createOnly bool) {
205195

206196
err = createContainer(context, container, namespace, spec)
207197
if err != nil {
208-
fmt.Fprintf(os.Stderr, "error %v\n", err)
209198
cmd.Process.Signal(syscall.SIGINT)
210-
os.Exit(-1)
199+
return fmt.Errorf("failed to create container: %v", err)
211200
}
212201
if !createOnly {
213202
address := filepath.Join(namespace, "namespaced.sock")
214203
startContainer(context, bundle, container, address, spec, context.Bool("detach"))
215204
}
216-
os.Exit(0)
205+
return nil
217206
}
218207

219-
func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) {
208+
func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) error {
220209
if context.String("console") != "" && context.String("console-socket") != "" {
221-
fmt.Fprintf(os.Stderr, "only one of --console & --console-socket can be specified")
222-
os.Exit(-1)
210+
return fmt.Errorf("only one of --console & --console-socket can be specified")
223211
}
224212
detach := createOnly
225213
if !createOnly {
226214
detach = context.Bool("detach")
227215
}
228216
if (context.String("console") != "" || context.String("console-socket") != "") && !detach {
229-
fmt.Fprintf(os.Stderr, "--console[-socket] should be used on detached mode\n")
230-
os.Exit(-1)
217+
return fmt.Errorf("--console[-socket] should be used on detached mode\n")
231218
}
232219
if (context.String("console") != "" || context.String("console-socket") != "") && !p.Terminal {
233-
fmt.Fprintf(os.Stderr, "--console[-socket] should be used on tty mode\n")
234-
os.Exit(-1)
220+
return fmt.Errorf("--console[-socket] should be used on tty mode\n")
235221
}
222+
return nil
236223
}
237224

238225
// Shared namespaces multiple containers suppurt
@@ -250,7 +237,10 @@ func checkConsole(context *cli.Context, p *specs.Process, createOnly bool) {
250237

251238
func createContainer(context *cli.Context, container, namespace string, config *specs.Spec) error {
252239
address := filepath.Join(namespace, "namespaced.sock")
253-
c := getClient(address)
240+
c, err := getClient(address)
241+
if err != nil {
242+
return err
243+
}
254244

255245
return ociCreate(context, container, func(stdin, stdout, stderr string) error {
256246
r := &types.CreateContainerRequest{
@@ -279,8 +269,7 @@ func createContainer(context *cli.Context, container, namespace string, config *
279269
func ociCreate(context *cli.Context, container string, createFunc func(stdin, stdout, stderr string) error) error {
280270
path, err := osext.Executable()
281271
if err != nil {
282-
fmt.Fprintf(os.Stderr, "cannot find self executable path for %s: %v\n", os.Args[0], err)
283-
os.Exit(-1)
272+
return fmt.Errorf("cannot find self executable path for %s: %v\n", os.Args[0], err)
284273
}
285274

286275
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)