github.com/apptainer/singularity@v3.1.1+incompatible/cmd/starter/main.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 main 7 8 /* 9 #include "c/message.c" 10 #include "c/capability.c" 11 #include "c/setns.c" 12 #include "c/starter.c" 13 */ 14 import "C" 15 16 import ( 17 "os" 18 "runtime" 19 "unsafe" 20 21 "github.com/sylabs/singularity/internal/app/starter" 22 "github.com/sylabs/singularity/internal/pkg/runtime/engines" 23 starterConfig "github.com/sylabs/singularity/internal/pkg/runtime/engines/config/starter" 24 "github.com/sylabs/singularity/internal/pkg/sylog" 25 "github.com/sylabs/singularity/internal/pkg/util/goversion" 26 "github.com/sylabs/singularity/internal/pkg/util/mainthread" 27 ) 28 29 func getEngine(jsonConfig []byte) *engines.Engine { 30 engine, err := engines.NewEngine(jsonConfig) 31 if err != nil { 32 sylog.Fatalf("failed to initialize runtime: %s\n", err) 33 } 34 return engine 35 } 36 37 func startup() { 38 loglevel := os.Getenv("SINGULARITY_MESSAGELEVEL") 39 os.Clearenv() 40 if loglevel != "" { 41 if os.Setenv("SINGULARITY_MESSAGELEVEL", loglevel) != nil { 42 sylog.Warningf("can't restore SINGULARITY_MESSAGELEVEL environment variable") 43 } 44 } 45 46 cconf := unsafe.Pointer(C.config) 47 sconfig := starterConfig.NewConfig(starterConfig.CConfig(cconf)) 48 jsonConfig := sconfig.GetJSONConfig() 49 50 switch C.execute { 51 case C.STAGE1: 52 sylog.Verbosef("Execute stage 1\n") 53 starter.Stage(int(C.STAGE1), int(C.master_socket[1]), sconfig, getEngine(jsonConfig)) 54 case C.STAGE2: 55 sylog.Verbosef("Execute stage 2\n") 56 if err := sconfig.Release(); err != nil { 57 sylog.Fatalf("%s", err) 58 } 59 60 mainthread.Execute(func() { 61 starter.Stage(int(C.STAGE2), int(C.master_socket[1]), sconfig, getEngine(jsonConfig)) 62 }) 63 case C.MASTER: 64 sylog.Verbosef("Execute master process\n") 65 66 isInstance := sconfig.GetInstance() 67 pid := sconfig.GetContainerPid() 68 69 if err := sconfig.Release(); err != nil { 70 sylog.Fatalf("%s", err) 71 } 72 73 starter.Master(int(C.rpc_socket[0]), int(C.master_socket[0]), isInstance, pid, getEngine(jsonConfig)) 74 case C.RPC_SERVER: 75 sylog.Verbosef("Serve RPC requests\n") 76 77 if err := sconfig.Release(); err != nil { 78 sylog.Fatalf("%s", err) 79 } 80 81 name := engines.GetName(jsonConfig) 82 starter.RPCServer(int(C.rpc_socket[1]), name) 83 } 84 sylog.Fatalf("You should not be there\n") 85 } 86 87 func init() { 88 // lock main thread for function execution loop 89 runtime.LockOSThread() 90 // this is mainly to reduce memory footprint 91 runtime.GOMAXPROCS(1) 92 } 93 94 func main() { 95 if err := goversion.Check(); err != nil { 96 sylog.Fatalf("%s", err) 97 } 98 99 // initialize runtime engines 100 engines.Init() 101 102 go startup() 103 104 // run functions requiring execution in main thread 105 for f := range mainthread.FuncChannel { 106 f() 107 } 108 }