github.com/apptainer/singularity@v3.1.1+incompatible/internal/app/singularity/oci_run_linux.go (about) 1 // Copyright (c) 2018-2019, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package singularity 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "os" 12 "path/filepath" 13 14 specs "github.com/opencontainers/runtime-spec/specs-go" 15 "github.com/sylabs/singularity/internal/pkg/instance" 16 "github.com/sylabs/singularity/internal/pkg/sylog" 17 "github.com/sylabs/singularity/pkg/ociruntime" 18 "github.com/sylabs/singularity/pkg/util/unix" 19 ) 20 21 // OciRun runs a container (equivalent to create/start/delete) 22 func OciRun(containerID string, args *OciArgs) error { 23 dir, err := instance.GetDirPrivileged(containerID, instance.OciSubDir) 24 if err != nil { 25 return err 26 } 27 if err := os.MkdirAll(dir, 0755); err != nil { 28 return err 29 } 30 args.SyncSocketPath = filepath.Join(dir, "run.sock") 31 32 l, err := unix.CreateSocket(args.SyncSocketPath) 33 if err != nil { 34 os.Remove(args.SyncSocketPath) 35 return err 36 } 37 38 defer l.Close() 39 40 status := make(chan string, 1) 41 42 if err := OciCreate(containerID, args); err != nil { 43 defer os.Remove(args.SyncSocketPath) 44 if _, err1 := getState(containerID); err1 != nil { 45 return err 46 } 47 if err := OciDelete(containerID); err != nil { 48 sylog.Warningf("can't delete container %s", containerID) 49 } 50 return err 51 } 52 53 defer exitContainer(containerID, true) 54 defer os.Remove(args.SyncSocketPath) 55 56 go func() { 57 var state specs.State 58 59 for { 60 c, err := l.Accept() 61 if err != nil { 62 status <- err.Error() 63 return 64 } 65 66 dec := json.NewDecoder(c) 67 if err := dec.Decode(&state); err != nil { 68 status <- err.Error() 69 return 70 } 71 72 c.Close() 73 74 switch state.Status { 75 case ociruntime.Created: 76 // ignore error there and wait for stopped status 77 OciStart(containerID) 78 case ociruntime.Running: 79 status <- state.Status 80 case ociruntime.Stopped: 81 status <- state.Status 82 } 83 } 84 }() 85 86 // wait running status 87 s := <-status 88 if s != ociruntime.Running { 89 return fmt.Errorf("%s", s) 90 } 91 92 engineConfig, err := getEngineConfig(containerID) 93 if err != nil { 94 return err 95 } 96 97 if err := attach(engineConfig, true); err != nil { 98 // kill container before deletion 99 sylog.Errorf("%s", err) 100 OciKill(containerID, "SIGKILL", 1) 101 return err 102 } 103 104 // wait stopped status 105 s = <-status 106 if s != ociruntime.Stopped { 107 return fmt.Errorf("%s", s) 108 } 109 110 return nil 111 }