// Convert and validate the GOAGAIN_FD, GOAGAIN_NAME, and GOAGAIN_PPID // environment variables. If all three are present and in order, this // is a child process that may pick up where the parent left off. func GetEnvs() (l *net.TCPListener, ppid int, err error) { var fd uintptr _, err = fmt.Sscan(os.Getenv("GOAGAIN_FD"), &fd) if nil != err { return } var i net.Listener i, err = net.FileListener(os.NewFile(fd, os.Getenv("GOAGAIN_NAME"))) if nil != err { return } l = i.(*net.TCPListener) if err = syscall.Close(int(fd)); nil != err { return } _, err = fmt.Sscan(os.Getenv("GOAGAIN_PPID"), &ppid) if nil != err { return } if syscall.Getppid() != ppid { err = errors.New(fmt.Sprintf( "GOAGAIN_PPID is %d but parent is %d\n", ppid, syscall.Getppid(), )) return } return }
// Convert and validate the GOAGAIN_FD and GOAGAIN_PPID environment // variables. If both are present and in order, this is a child process // that may pick up where the parent left off. func GetEnvs() (*net.TCPListener, int, error) { envFd := os.Getenv("GOAGAIN_FD") if "" == envFd { return nil, 0, errors.New("GOAGAIN_FD not set") } var fd uintptr _, err := fmt.Sscan(envFd, &fd) if nil != err { return nil, 0, err } tmp, err := net.FileListener(os.NewFile(fd, "listener")) if nil != err { return nil, 0, err } l := tmp.(*net.TCPListener) envPpid := os.Getenv("GOAGAIN_PPID") if "" == envPpid { return l, 0, errors.New("GOAGAIN_PPID not set") } var ppid int _, err = fmt.Sscan(envPpid, &ppid) if nil != err { return l, 0, err } if syscall.Getppid() != ppid { return l, ppid, errors.New(fmt.Sprintf( "GOAGAIN_PPID is %d but parent is %d\n", ppid, syscall.Getppid())) } return l, ppid, nil }
func (srv *FoolServer) Run() { /*{{{*/ logger = NewLog(srv.config.AccessLog, srv.config.ErrorLog, srv.config.RunLog) //解析模板 CompileTpl(srv.config.ViewPath) //信号处理函数 go srv.signalHandle() serverStat = STATE_RUNNING //kill父进程 if isChild == true { parent := syscall.Getppid() if _, err := os.FindProcess(parent); err != nil { return } logger.RunLog(fmt.Sprintf("[Notice] Killing parent pid: %v", parent)) syscall.Kill(parent, syscall.SIGQUIT) } srv.createPid(syscall.Getpid()) logger.RunLog("[Notice] Server start.") //listen loop srv.Serve(srv.listener) logger.RunLog("[Notice] Waiting for connections to finish...") connWg.Wait() serverStat = STATE_TERMINATE logger.RunLog("[Notice] Server shuttdown.") return } /*}}}*/
func TestCreateToolhelp32Snapshot(t *testing.T) { handle, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) if err != nil { t.Fatal(err) } defer syscall.CloseHandle(syscall.Handle(handle)) // Iterate over the snapshots until our PID is found. pid := uint32(syscall.Getpid()) for { process, err := Process32Next(handle) if errors.Cause(err) == syscall.ERROR_NO_MORE_FILES { break } if err != nil { t.Fatal(err) } t.Logf("CreateToolhelp32Snapshot: ProcessEntry32=%v", process) if process.ProcessID == pid { assert.EqualValues(t, syscall.Getppid(), process.ParentProcessID) return } } assert.Fail(t, "Snapshot not found for PID=%v", pid) }
func daemon(nochdir, noclose int) int { var ret, ret2 uintptr var err syscall.Errno darwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return 0 } // fork off the parent process ret, ret2, err = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return -1 } // failure if ret2 < 0 { os.Exit(-1) } // handle exception for darwin if darwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if ret > 0 { os.Exit(0) } /* Change the file mode mask */ _ = syscall.Umask(0) // create a new SID for the child process s_ret, s_errno := syscall.Setsid() if s_errno != nil { log.Printf("Error: syscall.Setsid errno: %d", s_errno) } if s_ret < 0 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return 0 }
func (t *trTransceiver) start(gracefulProtos string) error { t.startWorkers() t.startFlushers() t.startStatWorker() t.serviceMgr = newServiceManager(t) if err := t.serviceMgr.run(gracefulProtos); err != nil { return err } // Wait for workers/flushers to start correctly t.startWg.Wait() log.Printf("All workers running, good to go!") if gracefulProtos != "" { parent := syscall.Getppid() log.Printf("start(): Killing parent pid: %v", parent) syscall.Kill(parent, syscall.SIGTERM) log.Printf("start(): Waiting for the parent to signal that flush is complete...") ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGUSR1) s := <-ch log.Printf("start(): Received %v, proceeding to load the data", s) } t.dss.reload() // *finally* load the data (because graceful restart) go t.dispatcher() // now start dispatcher return nil }
// RestoreParentDeathSignal sets the parent death signal to old. func RestoreParentDeathSignal(old int) error { if old == 0 { return nil } current, err := system.GetParentDeathSignal() if err != nil { return fmt.Errorf("get parent death signal %s", err) } if old == current { return nil } if err := system.ParentDeathSignal(uintptr(old)); err != nil { return fmt.Errorf("set parent death signal %s", err) } // Signal self if parent is already dead. Does nothing if running in a new // PID namespace, as Getppid will always return 0. if syscall.Getppid() == 1 { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return nil }
func (this torUtil) SetDaemonMode(nochdir, noclose int) int { if syscall.Getppid() == 1 { return 0 } ret, ret2, err := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if err != 0 { return -1 } if ret2 < 0 { os.Exit(-1) } if ret > 0 { os.Exit(0) } syscall.Umask(0) s_ret, s_errno := syscall.Setsid() if s_ret < 0 { return -1 } if nochdir == 0 { os.Chdir("/") } if noclose == 0 { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return 0 }
// blocks on the server ready and when ready, it sends // a signal to the parent so that it knows it cna now exit func childReady(srv *falcore.Server) { pid := syscall.Getpid() // wait for the ready signal <-srv.AcceptReady // grab the parent and send a signal that the child is ready parent := syscall.Getppid() fmt.Printf("%v Kill parent %v with SIGUSR1\n", pid, parent) syscall.Kill(parent, syscall.SIGUSR1) }
func start(c *cli.Context) { if pidfile != "" { pid, err := fileOrPid(pidfile) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } if pid != 0 && pid != syscall.Getppid() { fmt.Fprintf(os.Stderr, "There is already a pidfile at '%s' that appears to belong to another apiplexy instance.") os.Exit(1) } } if configPath == "" { configPath = c.String("config") } ap, config, err := initApiplex(configPath) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } server := &http.Server{ Addr: "0.0.0.0:" + strconv.Itoa(config.Serve.Port), Handler: ap, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, MaxHeaderBytes: 1 << 16, } fmt.Printf("Launching apiplexy on port %d.\n", config.Serve.Port) l, err := net.Listen("tcp", server.Addr) if err != nil { fmt.Fprintf(os.Stderr, "Couldn't start server on %s: %s\n", server.Addr, err.Error()) os.Exit(1) } // write pidfile and wait for restart signal if pidfile != "" { ioutil.WriteFile(pidfile, []byte(strconv.Itoa(syscall.Getpid())), 0600) } defer func() { // server shuts down, delete pidfile if it's still our PID in there if pidfile != "" { rp, _ := ioutil.ReadFile(pidfile) p, _ := strconv.Atoi(string(rp)) if p == syscall.Getpid() { os.Remove(pidfile) } } }() server.Serve(l) }
func NewDefaultFormatter(out io.Writer) Formatter { if syscall.Getppid() == 1 { // We're running under init, which may be systemd. f, err := NewJournaldFormatter() if err == nil { return f } } return NewPrettyFormatter(out, false) }
func _not_work_Fork(closeno bool) (pid int, err error) { // don't run this // not work with go threads // see: http://code.google.com/p/go/issues/detail?id=227 darwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return 0, nil } // fork off the parent process ret, ret2, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return -1, fmt.Errorf("Fork failure: %s", errno) } // failure if ret2 < 0 { return -1, fmt.Errorf("Fork failure") } // handle exception for darwin if darwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if ret > 0 { return 0, nil } // create a new SID for the child process s_ret, s_errno := syscall.Setsid() if s_errno != nil { return -1, fmt.Errorf("Error: syscall.Setsid: %s", s_errno) } if s_ret < 0 { return -1, fmt.Errorf("Error: syscall.Setsid: %s", s_errno) } if closeno { f, e := os.OpenFile("/dev/null", os.O_RDWR, 0) if e == nil { fd := int(f.Fd()) syscall.Dup2(fd, int(os.Stdin.Fd())) syscall.Dup2(fd, int(os.Stdout.Fd())) syscall.Dup2(fd, int(os.Stderr.Fd())) } } return os.Getpid(), nil }
func main() { conf := flag.String("conf", "./conf/pmon.json", "config file") var gracefulChild bool flag.BoolVar(&gracefulChild, "graceful", false, "listen on fd open 3 (internal use only)") flag.Parse() defer glog.Flush() var err error confPath, err = filepath.Abs(*conf) if nil != err { glog.Errorf("%v", err) return } // sc := make(chan os.Signal, 1) // signal.Notify(sc, os.Interrupt, os.Kill) // go func() { // _ = <-sc // killAll(&LogWriter{}) // glog.Flush() // os.Exit(1) // }() watchConfFile() //start admin server var l net.Listener if gracefulChild { f := os.NewFile(3, "") l, err = net.FileListener(f) } else { l, err = net.Listen("tcp", Cfg.Listen) } if nil != err { glog.Errorf("Bind socket failed:%v", err) return } tl := l.(*net.TCPListener) listenFile, _ = tl.File() if gracefulChild { parent := syscall.Getppid() glog.Infof("main: Killing parent pid: %v", parent) if proc, _ := os.FindProcess(parent); nil != proc { proc.Signal(syscall.SIGTERM) } //syscall.Kill(parent, syscall.SIGTERM) } for { c, _ := l.Accept() if nil != c { processAdminConn(c) //only ONE admin connection allowd } } }
// Convert and validate the GOAGAIN_FD, GOAGAIN_NAME, and GOAGAIN_PPID // environment variables. If all three are present and in order, this // is a child process that may pick up where the parent left off. func GetEnvs() (l net.Listener, ppid int, err error) { var fd uintptr _, err = fmt.Sscan(os.Getenv("GOAGAIN_FD"), &fd) if nil != err { return } var i net.Listener i, err = net.FileListener(os.NewFile(fd, os.Getenv("GOAGAIN_NAME"))) if nil != err { return } switch i.(type) { case *net.TCPListener: l = i.(*net.TCPListener) case *net.UnixListener: l = i.(*net.UnixListener) default: err = errors.New(fmt.Sprintf( "file descriptor is %T not *net.TCPListener or *net.UnixListener", i, )) return } if err = syscall.Close(int(fd)); nil != err { return } _, err = fmt.Sscan(os.Getenv("GOAGAIN_PPID"), &ppid) if nil != err { return } if syscall.Getppid() != ppid { err = errors.New(fmt.Sprintf( "GOAGAIN_PPID is %d but parent is %d", ppid, syscall.Getppid(), )) return } return }
func daemon() error { isDarwin := runtime.GOOS == "darwin" // already a daemon if syscall.Getppid() == 1 { return nil } // fork off the parent process ret, ret2, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return errors.New(fmt.Sprintf("fork error! [errno=%d]", errno)) } // failure if ret2 < 0 { os.Exit(1) } // handle exception for darwin if isDarwin && ret2 == 1 { ret = 0 } // if we got a good PID, then we call exit the parent process. if int(ret) > 0 { os.Exit(0) } syscall.Umask(0) // create a new SID for the child process _, err := syscall.Setsid() if err != nil { return err } //os.Chdir("/") f, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err == nil { fd := f.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return nil }
// TestFcntlFlock tests whether the file locking structure matches // the calling convention of each kernel. // On some Linux systems, glibc uses another set of values for the // commands and translates them to the correct value that the kernel // expects just before the actual fcntl syscall. As Go uses raw // syscalls directly, it must use the real value, not the glibc value. // Thus this test also verifies that the Flock_t structure can be // roundtripped with F_SETLK and F_GETLK. func TestFcntlFlock(t *testing.T) { if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { t.Skip("skipping; no child processes allowed on iOS") } flock := syscall.Flock_t{ Type: syscall.F_WRLCK, Start: 31415, Len: 271828, Whence: 1, } if os.Getenv("GO_WANT_HELPER_PROCESS") == "" { // parent name := filepath.Join(os.TempDir(), "TestFcntlFlock") fd, err := syscall.Open(name, syscall.O_CREAT|syscall.O_RDWR|syscall.O_CLOEXEC, 0) if err != nil { t.Fatalf("Open failed: %v", err) } defer syscall.Unlink(name) defer syscall.Close(fd) if err := syscall.Ftruncate(fd, 1<<20); err != nil { t.Fatalf("Ftruncate(1<<20) failed: %v", err) } if err := syscall.FcntlFlock(uintptr(fd), syscall.F_SETLK, &flock); err != nil { t.Fatalf("FcntlFlock(F_SETLK) failed: %v", err) } cmd := exec.Command(os.Args[0], "-test.run=^TestFcntlFlock$") cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1") cmd.ExtraFiles = []*os.File{os.NewFile(uintptr(fd), name)} out, err := cmd.CombinedOutput() if len(out) > 0 || err != nil { t.Fatalf("child process: %q, %v", out, err) } } else { // child got := flock // make sure the child lock is conflicting with the parent lock got.Start-- got.Len++ if err := syscall.FcntlFlock(3, syscall.F_GETLK, &got); err != nil { t.Fatalf("FcntlFlock(F_GETLK) failed: %v", err) } flock.Pid = int32(syscall.Getppid()) // Linux kernel always set Whence to 0 flock.Whence = 0 if got.Type == flock.Type && got.Start == flock.Start && got.Len == flock.Len && got.Pid == flock.Pid && got.Whence == flock.Whence { os.Exit(0) } t.Fatalf("FcntlFlock got %v, want %v", got, flock) } }
func main() { var numcalls int var err error args := Arguments() if !args.Exist() { numcalls = 10000000 } else { numcalls, args, err = args.Int("n", 0, 0) Check(err) } log.Println("Calling syscall.Getppid()") for i := 0; i < numcalls; i++ { syscall.Getppid() } }
// 检查必要环境 func (s *GoServer) checkEnv() { if syscall.Getppid() == 1 { log.Fatal("server already started") os.Exit(1) } // 检查指定的worker用户是否合法 s.checkWorkerUserName() // 检查log目录是否可读 s.checkLogWriteAble() // 检查配置和语法错误等 s.checkWorkersConfig() // 检查文件限制 s.checkLimit() }
func Daemon(nochdir int) error { signal.Ignore(syscall.SIGINT, syscall.SIGHUP, syscall.SIGPIPE) if syscall.Getppid() == 1 { return nil } ret1, ret2, eno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if eno != 0 || ret2 < 0 { return errors.New("Fork fail") } /* exit parent */ if ret1 > 0 { os.Exit(0) } _ = syscall.Umask(0) ret, err := syscall.Setsid() if ret < 0 || err != nil { return errors.New("Set sid failed") } if nochdir == 0 { err = os.Chdir("/") if err != nil { return errors.New("Chdir failed") } } file, err := os.OpenFile("/dev/null", os.O_RDWR, 0) if err == nil { fd := file.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) // syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return nil }
func DoDaemon(log, chdir string) (err error) { syscall.Umask(0) if chdir != "" { os.Chdir(chdir) } if syscall.Getppid() == 1 { return } files := make([]*os.File, 3, 6) if log != "" { fp, err := os.OpenFile(log, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { return err } files[0], files[1], files[2] = fp, fp, fp } else { files[0], files[1], files[2] = os.Stdin, os.Stdout, os.Stderr } dir, _ := os.Getwd() sysattrs := syscall.SysProcAttr{Setsid: true} prcattrs := os.ProcAttr{ Dir: dir, Env: os.Environ(), Files: files, Sys: &sysattrs, } proc, err := os.StartProcess(os.Args[0], os.Args, &prcattrs) if err != nil { return } proc.Release() os.Exit(0) return }
func newContainerInit(t initType, pipe *os.File) (initer, error) { var config *initConfig if err := json.NewDecoder(pipe).Decode(&config); err != nil { return nil, err } if err := populateProcessEnvironment(config.Env); err != nil { return nil, err } switch t { case initSetns: return &linuxSetnsInit{ config: config, }, nil case initStandard: return &linuxStandardInit{ parentPid: syscall.Getppid(), config: config, }, nil } return nil, fmt.Errorf("unknown init type %q", t) }
/* ListenAndServeTLS listens on the TCP network address srv.EndlessListener.Addr() and then calls Serve to handle requests on incoming TLS connections. Filenames containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate. If srv.EndlessListener.Addr() is blank, ":https" is used. */ func (srv *endlessServer) ListenAndServeTLS(certFile, keyFile string) (err error) { addr := srv.Addr if addr == "" { addr = ":https" } config := &tls.Config{} if srv.TLSConfig() != nil { *config = *srv.TLSConfig() } if config.NextProtos == nil { config.NextProtos = []string{"http/1.1"} } config.Certificates = make([]tls.Certificate, 1) config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return } go srv.handleSignals() l, err := srv.getListener(addr) if err != nil { log.Println(err) return } srv.tlsInnerListener = newEndlessListener(l, srv) srv.EndlessListener = tls.NewListener(srv.tlsInnerListener, config) if srv.isChild { syscall.Kill(syscall.Getppid(), syscall.SIGTERM) } log.Println(syscall.Getpid(), srv.EndlessListener.Addr(), "ListenAndServeTLS") return srv.Serve() }
func Daemon(chdir bool, clstd bool) (err error) { var ret1, ret2 uintptr var er syscall.Errno darwin := runtime.GOOS == "darwin" if syscall.Getppid() == 1 { return } ret1, ret2, er = syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if er != 0 { err = errors.New("daemon fork fail") return } if ret2 < 0 { err = errors.New("fork return fail") os.Exit(-1) } if darwin && ret2 == 1 { ret1 = 0 } if ret1 > 0 { os.Exit(0) } syscall.Umask(0) syscall.Setsid() if chdir { os.Chdir("/") } if clstd { fs, err := os.OpenFile(os.DevNull, os.O_RDWR, 0) if err == nil { fd := fs.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } } return }
// Re-exec this same image without dropping the net.Listener. func Exec(l net.Listener) error { var pid int fmt.Sscan(os.Getenv("GOAGAIN_PID"), &pid) if syscall.Getppid() == pid { return fmt.Errorf("goagain.Exec called by a child process") } argv0, err := lookPath() if nil != err { return err } if _, err := setEnvs(l); nil != err { return err } if err := os.Setenv( "GOAGAIN_SIGNAL", fmt.Sprintf("%d", syscall.SIGQUIT), ); nil != err { return err } log.Println("re-executing", argv0) return syscall.Exec(argv0, os.Args, os.Environ()) }
/* ListenAndServe listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming connections. If srv.Addr is blank, ":http" is used. */ func (srv *endlessServer) ListenAndServe() (err error) { addr := srv.Addr if addr == "" { addr = ":http" } go srv.handleSignals() l, err := srv.getListener(addr) if err != nil { log.Println(err) return } srv.EndlessListener = newEndlessListener(l, srv) if srv.isChild { syscall.Kill(syscall.Getppid(), syscall.SIGTERM) } log.Println(syscall.Getpid(), srv.Addr) return srv.Serve() }
func Daemon(nochdir, noclose int) (int, error) { // already a daemon if syscall.Getppid() == 1 { /* Change the file mode mask */ syscall.Umask(0) if nochdir == 0 { os.Chdir("/") } return 0, nil } files := make([]*os.File, 3, 6) if noclose == 0 { nullDev, err := os.OpenFile("/dev/null", 0, 0) if err != nil { return 1, err } files[0], files[1], files[2] = nullDev, nullDev, nullDev } else { files[0], files[1], files[2] = os.Stdin, os.Stdout, os.Stderr } dir, _ := os.Getwd() sysattrs := syscall.SysProcAttr{Setsid: true} attrs := os.ProcAttr{Dir: dir, Env: os.Environ(), Files: files, Sys: &sysattrs} proc, err := os.StartProcess(os.Args[0], os.Args, &attrs) if err != nil { return -1, fmt.Errorf("can't create process %s: %s", os.Args[0], err) } proc.Release() os.Exit(0) return 0, nil }
func (l *linuxStandardInit) Init() error { // do not inherit the parent's session keyring sessKeyId, err := keyctl.JoinSessionKeyring("") if err != nil { return err } // make session keyring searcheable // without user ns we need 'UID' search permissions // with user ns we need 'other' search permissions if err := keyctl.ModKeyringPerm(sessKeyId, 0xffffffff, 0x080008); err != nil { return err } // join any namespaces via a path to the namespace fd if provided if err := joinExistingNamespaces(l.config.Config.Namespaces); err != nil { return err } var console *linuxConsole if l.config.Console != "" { console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } } if _, err := syscall.Setsid(); err != nil { return err } if console != nil { if err := system.Setctty(); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } if err := setupRlimits(l.config.Config); err != nil { return err } if err := setOomScoreAdj(l.config.Config.OomScoreAdj); err != nil { return err } label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := setupRootfs(l.config.Config, console); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.Config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.Config.ProcessLabel); err != nil { return err } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { return err } } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskFile(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if l.config.Config.NoNewPrivileges { if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { return err } } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { return err } if l.config.Config.Seccomp != nil { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // compare the parent from the inital start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparened to something else so we should // just kill ourself and not cause problems for someone else. if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }
// Getppid returns the process id of the caller's parent. func Getppid() int { return syscall.Getppid() }
func Daemon(pfile, lfile string, uid, gid, nochdir, noclose int) int { if syscall.Getppid() == 1 { return 0 } ret, mret, errno := syscall.RawSyscall(syscall.SYS_FORK, 0, 0, 0) if errno != 0 { return -1 } if mret < 0 { os.Exit(-1) } if runtime.GOOS == "darwin" && mret == 1 { ret = 0 } if ret > 0 { os.Exit(0) } _ = syscall.Umask(0) s_ret, err := syscall.Setsid() if err != nil { panic(err) } if s_ret < 0 { return -1 } err = WriteFile(pfile, fmt.Sprintf("%d\n", os.Getpid())) if err != nil { panic(err) } /* err = syscall.Setgid(gid) if err != nil { panic(err) } err = syscall.Setuid(uid) if err != nil { panic(err) } */ if nochdir == 0 { os.Chdir("/") } if noclose == 0 { fp, err := os.OpenFile(lfile, os.O_RDWR|os.O_APPEND, 0) if err != nil { panic(err) } fd := fp.Fd() syscall.Dup2(int(fd), int(os.Stdin.Fd())) syscall.Dup2(int(fd), int(os.Stdout.Fd())) syscall.Dup2(int(fd), int(os.Stderr.Fd())) } return 0 }
func (l *linuxStandardInit) Init() error { ringname, keepperms, newperms := l.getSessionRingParams() // do not inherit the parent's session keyring sessKeyId, err := keyctl.JoinSessionKeyring(ringname) if err != nil { return err } // make session keyring searcheable if err := keyctl.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { return err } var console *linuxConsole if l.config.Console != "" { console = newConsoleFromPath(l.config.Console) if err := console.dupStdio(); err != nil { return err } } if console != nil { if err := system.Setctty(); err != nil { return err } } if err := setupNetwork(l.config); err != nil { return err } if err := setupRoute(l.config.Config); err != nil { return err } label.Init() // InitializeMountNamespace() can be executed only for a new mount namespace if l.config.Config.Namespaces.Contains(configs.NEWNS) { if err := setupRootfs(l.config.Config, console, l.pipe); err != nil { return err } } if hostname := l.config.Config.Hostname; hostname != "" { if err := syscall.Sethostname([]byte(hostname)); err != nil { return err } } if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil { return err } if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil { return err } for key, value := range l.config.Config.Sysctl { if err := writeSystemProperty(key, value); err != nil { return err } } for _, path := range l.config.Config.ReadonlyPaths { if err := remountReadonly(path); err != nil { return err } } for _, path := range l.config.Config.MaskPaths { if err := maskFile(path); err != nil { return err } } pdeath, err := system.GetParentDeathSignal() if err != nil { return err } if l.config.NoNewPrivileges { if err := system.Prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil { return err } } // Tell our parent that we're ready to Execv. This must be done before the // Seccomp rules have been applied, because we need to be able to read and // write to a socket. if err := syncParentReady(l.pipe); err != nil { return err } // Without NoNewPrivileges seccomp is a privileged operation, so we need to // do this before dropping capabilities; otherwise do it as late as possible // just before execve so as few syscalls take place after it as possible. if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } if err := finalizeNamespace(l.config); err != nil { return err } // finalizeNamespace can change user/group which clears the parent death // signal, so we restore it here. if err := pdeath.Restore(); err != nil { return err } // compare the parent from the inital start of the init process and make sure that it did not change. // if the parent changes that means it died and we were reparened to something else so we should // just kill ourself and not cause problems for someone else. if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges { if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil { return err } } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ()) }