@@ -20,6 +20,7 @@ import (
2020 "golang.org/x/sys/unix"
2121
2222 "github.com/opencontainers/cgroups"
23+ "github.com/opencontainers/runc/internal/linux"
2324 "github.com/opencontainers/runc/libcontainer/configs"
2425 "github.com/opencontainers/runc/libcontainer/exeseal"
2526 "github.com/opencontainers/runc/libcontainer/intelrdt"
@@ -231,74 +232,19 @@ func (c *Container) Exec() error {
231232}
232233
233234func (c * Container ) exec () error {
234- path := filepath .Join (c .stateDir , execFifoFilename )
235- pid := c .initProcess .pid ()
236- blockingFifoOpenCh := awaitFifoOpen (path )
237- for {
238- select {
239- case result := <- blockingFifoOpenCh :
240- return handleFifoResult (result )
241-
242- case <- time .After (time .Millisecond * 100 ):
243- stat , err := system .Stat (pid )
244- if err != nil || stat .State == system .Zombie {
245- // could be because process started, ran, and completed between our 100ms timeout and our system.Stat() check.
246- // see if the fifo exists and has data (with a non-blocking open, which will succeed if the writing process is complete).
247- if err := handleFifoResult (fifoOpen (path , false )); err != nil {
248- return errors .New ("container process is already dead" )
249- }
250- return nil
251- }
252- }
253- }
254- }
255-
256- func readFromExecFifo (execFifo io.Reader ) error {
257- data , err := io .ReadAll (execFifo )
235+ fifoPath := filepath .Join (c .stateDir , execFifoFilename )
236+ fd , err := linux .Open (fifoPath , unix .O_WRONLY | unix .O_CLOEXEC , 0 )
258237 if err != nil {
259238 return err
260239 }
261- if len (data ) <= 0 {
262- return errors .New ("cannot start an already running container" )
240+ defer unix .Close (fd )
241+ if _ , err := unix .Write (fd , []byte ("0" )); err != nil {
242+ return & os.PathError {Op : "write exec fifo" , Path : fifoPath , Err : err }
263243 }
264- return nil
265- }
266-
267- func awaitFifoOpen (path string ) <- chan openResult {
268- fifoOpened := make (chan openResult )
269- go func () {
270- result := fifoOpen (path , true )
271- fifoOpened <- result
272- }()
273- return fifoOpened
274- }
275-
276- func fifoOpen (path string , block bool ) openResult {
277- flags := os .O_RDONLY
278- if ! block {
279- flags |= unix .O_NONBLOCK
280- }
281- f , err := os .OpenFile (path , flags , 0 )
282- if err != nil {
283- return openResult {err : fmt .Errorf ("exec fifo: %w" , err )}
284- }
285- return openResult {file : f }
286- }
287-
288- func handleFifoResult (result openResult ) error {
289- if result .err != nil {
290- return result .err
291- }
292- f := result .file
293- defer f .Close ()
294- if err := readFromExecFifo (f ); err != nil {
244+ if err := os .Remove (fifoPath ); os .IsNotExist (err ) {
295245 return err
296246 }
297- err := os .Remove (f .Name ())
298- if err == nil || os .IsNotExist (err ) {
299- return nil
300- }
301- return err
247+ return nil
302248}
303249
304250type openResult struct {
@@ -450,7 +396,7 @@ func (c *Container) createExecFifo() (retErr error) {
450396 }
451397
452398 fifoName := filepath .Join (c .stateDir , execFifoFilename )
453- if err := unix .Mkfifo (fifoName , 0o622 ); err != nil {
399+ if err := unix .Mkfifo (fifoName , 0o644 ); err != nil {
454400 return & os.PathError {Op : "mkfifo" , Path : fifoName , Err : err }
455401 }
456402 defer func () {
@@ -459,7 +405,7 @@ func (c *Container) createExecFifo() (retErr error) {
459405 }
460406 }()
461407 // Ensure permission bits (can be different because of umask).
462- if err := os .Chmod (fifoName , 0o622 ); err != nil {
408+ if err := os .Chmod (fifoName , 0o644 ); err != nil {
463409 return err
464410 }
465411 return os .Chown (fifoName , rootuid , rootgid )
0 commit comments