17
17
package runc
18
18
19
19
import (
20
+ "bytes"
20
21
"context"
21
22
"encoding/json"
22
23
"errors"
@@ -72,11 +73,12 @@ type Runc struct {
72
73
// List returns all containers created inside the provided runc root directory
73
74
func (r * Runc ) List (context context.Context ) ([]* Container , error ) {
74
75
data , err := cmdOutput (r .command (context , "list" , "--format=json" ), false )
76
+ defer putBuf (data )
75
77
if err != nil {
76
78
return nil , err
77
79
}
78
80
var out []* Container
79
- if err := json .Unmarshal (data , & out ); err != nil {
81
+ if err := json .Unmarshal (data . Bytes () , & out ); err != nil {
80
82
return nil , err
81
83
}
82
84
return out , nil
@@ -85,11 +87,12 @@ func (r *Runc) List(context context.Context) ([]*Container, error) {
85
87
// State returns the state for the container provided by id
86
88
func (r * Runc ) State (context context.Context , id string ) (* Container , error ) {
87
89
data , err := cmdOutput (r .command (context , "state" , id ), true )
90
+ defer putBuf (data )
88
91
if err != nil {
89
- return nil , fmt .Errorf ("%s: %s" , err , data )
92
+ return nil , fmt .Errorf ("%s: %s" , err , data . String () )
90
93
}
91
94
var c Container
92
- if err := json .Unmarshal (data , & c ); err != nil {
95
+ if err := json .Unmarshal (data . Bytes () , & c ); err != nil {
93
96
return nil , err
94
97
}
95
98
return & c , nil
@@ -154,8 +157,9 @@ func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOp
154
157
155
158
if cmd .Stdout == nil && cmd .Stderr == nil {
156
159
data , err := cmdOutput (cmd , true )
160
+ defer putBuf (data )
157
161
if err != nil {
158
- return fmt .Errorf ("%s: %s" , err , data )
162
+ return fmt .Errorf ("%s: %s" , err , data . String () )
159
163
}
160
164
return nil
161
165
}
@@ -233,8 +237,9 @@ func (r *Runc) Exec(context context.Context, id string, spec specs.Process, opts
233
237
}
234
238
if cmd .Stdout == nil && cmd .Stderr == nil {
235
239
data , err := cmdOutput (cmd , true )
240
+ defer putBuf (data )
236
241
if err != nil {
237
- return fmt .Errorf ("%s: %s" , err , data )
242
+ return fmt .Errorf ("%s: %s" , err , data . String () )
238
243
}
239
244
return nil
240
245
}
@@ -399,11 +404,12 @@ func (r *Runc) Resume(context context.Context, id string) error {
399
404
// Ps lists all the processes inside the container returning their pids
400
405
func (r * Runc ) Ps (context context.Context , id string ) ([]int , error ) {
401
406
data , err := cmdOutput (r .command (context , "ps" , "--format" , "json" , id ), true )
407
+ defer putBuf (data )
402
408
if err != nil {
403
- return nil , fmt .Errorf ("%s: %s" , err , data )
409
+ return nil , fmt .Errorf ("%s: %s" , err , data . String () )
404
410
}
405
411
var pids []int
406
- if err := json .Unmarshal (data , & pids ); err != nil {
412
+ if err := json .Unmarshal (data . Bytes () , & pids ); err != nil {
407
413
return nil , err
408
414
}
409
415
return pids , nil
@@ -412,11 +418,12 @@ func (r *Runc) Ps(context context.Context, id string) ([]int, error) {
412
418
// Top lists all the processes inside the container returning the full ps data
413
419
func (r * Runc ) Top (context context.Context , id string , psOptions string ) (* TopResults , error ) {
414
420
data , err := cmdOutput (r .command (context , "ps" , "--format" , "table" , id , psOptions ), true )
421
+ defer putBuf (data )
415
422
if err != nil {
416
- return nil , fmt .Errorf ("%s: %s" , err , data )
423
+ return nil , fmt .Errorf ("%s: %s" , err , data . String () )
417
424
}
418
425
419
- topResults , err := ParsePSOutput (data )
426
+ topResults , err := ParsePSOutput (data . Bytes () )
420
427
if err != nil {
421
428
return nil , fmt .Errorf ("%s: " , err )
422
429
}
@@ -606,10 +613,11 @@ type Version struct {
606
613
// Version returns the runc and runtime-spec versions
607
614
func (r * Runc ) Version (context context.Context ) (Version , error ) {
608
615
data , err := cmdOutput (r .command (context , "--version" ), false )
616
+ defer putBuf (data )
609
617
if err != nil {
610
618
return Version {}, err
611
619
}
612
- return parseVersion (data )
620
+ return parseVersion (data . Bytes () )
613
621
}
614
622
615
623
func parseVersion (data []byte ) (Version , error ) {
@@ -687,15 +695,17 @@ func (r *Runc) runOrError(cmd *exec.Cmd) error {
687
695
return err
688
696
}
689
697
data , err := cmdOutput (cmd , true )
698
+ defer putBuf (data )
690
699
if err != nil {
691
- return fmt .Errorf ("%s: %s" , err , data )
700
+ return fmt .Errorf ("%s: %s" , err , data . String () )
692
701
}
693
702
return nil
694
703
}
695
704
696
- func cmdOutput (cmd * exec.Cmd , combined bool ) ([]byte , error ) {
705
+ // callers of cmdOutput are expected to call putBuf on the returned Buffer
706
+ // to ensure it is released back to the shared pool after use.
707
+ func cmdOutput (cmd * exec.Cmd , combined bool ) (* bytes.Buffer , error ) {
697
708
b := getBuf ()
698
- defer putBuf (b )
699
709
700
710
cmd .Stdout = b
701
711
if combined {
@@ -711,5 +721,5 @@ func cmdOutput(cmd *exec.Cmd, combined bool) ([]byte, error) {
711
721
err = fmt .Errorf ("%s did not terminate successfully" , cmd .Args [0 ])
712
722
}
713
723
714
- return b . Bytes () , err
724
+ return b , err
715
725
}
0 commit comments