@@ -48,7 +48,8 @@ type Container struct {
4848 id string
4949
5050 vsock transport.Transport
51- logFile * os.File
51+ logPath string // path to [logFile].
52+ logFile * os.File // file to redirect container's stdio to.
5253
5354 spec * oci.Spec
5455 ociBundlePath string
@@ -77,14 +78,37 @@ type Container struct {
7778 scratchDirPath string
7879}
7980
80- func (c * Container ) Start (ctx context.Context , conSettings stdio.ConnectionSettings ) (int , error ) {
81- log .G (ctx ).WithField (logfields .ContainerID , c .id ).Info ("opengcs::Container::Start" )
81+ func (c * Container ) Start (ctx context.Context , conSettings stdio.ConnectionSettings ) (_ int , err error ) {
82+ entity := log .G (ctx ).WithField (logfields .ContainerID , c .id )
83+ entity .Info ("opengcs::Container::Start" )
8284
8385 // only use the logfile for the init process, since we don't want to tee stdio of execs
8486 t := c .vsock
85- if c .logFile != nil {
87+ if c .logPath != "" {
88+ // don't use [os.Create] since that truncates an existing file, which is not desired
89+ if c .logFile , err = os .OpenFile (c .logPath , os .O_RDWR | os .O_CREATE , 0666 ); err != nil {
90+ return - 1 , fmt .Errorf ("failed to open log file: %s: %w" , c .logPath , err )
91+ }
92+ go func () {
93+ // initProcess is already created in [(*Host).CreateContainer], and is, therefore, "waitable"
94+ // wait in `writersWg`, which is closed after process is cleaned up (including io Relays)
95+ //
96+ // Note: [PipeRelay] and [TtyRelay] are not safe to call multiple times, so it is safer to wait
97+ // on the parent (init) process.
98+ c .initProcess .writersWg .Wait ()
99+
100+ if lfErr := c .logFile .Close (); lfErr != nil {
101+ entity .WithFields (logrus.Fields {
102+ logrus .ErrorKey : err ,
103+ logfields .Path : c .logFile .Name (),
104+ }).Warn ("failed to close log file" )
105+ }
106+ c .logFile = nil
107+ }()
108+
86109 t = transport .NewMultiWriter (c .vsock , c .logFile )
87110 }
111+
88112 stdioSet , err := stdio .Connect (t , conSettings )
89113 if err != nil {
90114 return - 1 , err
@@ -189,24 +213,12 @@ func (c *Container) GetAllProcessPids(ctx context.Context) ([]int, error) {
189213
190214// Kill sends 'signal' to the container process.
191215func (c * Container ) Kill (ctx context.Context , signal syscall.Signal ) error {
192- entity := log .G (ctx ).WithField (logfields .ContainerID , c .id )
193- entity .Info ("opengcs::Container::Kill" )
216+ log .G (ctx ).WithField (logfields .ContainerID , c .id ).Info ("opengcs::Container::Kill" )
194217 err := c .container .Kill (signal )
195218 if err != nil {
196219 return err
197220 }
198-
199221 c .setExitType (signal )
200- if c .logFile != nil {
201- if err = c .logFile .Close (); err != nil {
202- entity .WithFields (logrus.Fields {
203- logrus .ErrorKey : err ,
204- logfields .Path : c .logFile .Name (),
205- }).Warn ("failed to close log file" )
206- }
207- c .logFile = nil
208- }
209-
210222 return nil
211223}
212224
0 commit comments