@@ -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,76 +232,18 @@ 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 }
264244 return nil
265245}
266246
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 {
295- return err
296- }
297- err := os .Remove (f .Name ())
298- if err == nil || os .IsNotExist (err ) {
299- return nil
300- }
301- return err
302- }
303-
304247type openResult struct {
305248 file * os.File
306249 err error
0 commit comments