Exemplo n.º 1
0
// ensureOwnerExists makes sure that at least one owner exists in the database.
func (bot *Bot) ensureOwnerExists() {
	result, err := bot.Db.Query(`SELECT EXISTS(SELECT 1 FROM users WHERE owner=1 LIMIT 1);`)
	if err != nil {
		bot.Log.Fatalf("Can't check if owner exists: %s", err)
	}
	defer result.Close()

	if result.Next() {
		var ownerExists bool
		if err = result.Scan(&ownerExists); err != nil {
			bot.Log.Fatalf("Can't check if owner exists: %s", err)
		}
		if !ownerExists {
			bot.Log.Warningf("No owner found in the database. Must create one.")

			stty, _ := exec.LookPath("stty")
			sttyArgs := syscall.ProcAttr{
				"",
				[]string{},
				[]uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
				nil,
			}
			reader := bufio.NewReader(os.Stdin)

			fmt.Print("Enter owner's nick: ")
			nick, _ := reader.ReadString('\n')

			// Disable echo.
			if stty != "" {
				syscall.ForkExec(stty, []string{"stty", "-echo"}, &sttyArgs)
			}

			// Get password.
			fmt.Print("Enter owner's password: "******"\nConfirm owner's password: "******"Passwords don't match.")
			}
			fmt.Print("\n")

			// Enable echo.
			if stty != "" {
				syscall.ForkExec(stty, []string{"stty", "echo"}, &sttyArgs)
			}

			result.Close()

			if bot.addUser(utils.CleanString(nick, false), utils.CleanString(pass1, false), true, true); err != nil {
				bot.Log.Fatalf("%s", err)
			}
		}
	}
}
Exemplo n.º 2
0
// echoOff turns off the terminal echo.
func echoOff(fd []uintptr) (int, error) {
	pid, err := syscall.ForkExec(sttyArg0, sttyArgvEOff, &syscall.ProcAttr{Dir: "", Files: fd})
	if err != nil {
		return 0, fmt.Errorf("failed turning off console echo for password entry:\n\t%s", err)
	}
	return pid, nil
}
Exemplo n.º 3
0
func (pluginReg *PluginReg) startPlugin(startFile string) (int, error) {

	// Change the file permission
	err := os.Chmod(startFile, 0777)
	if err != nil {
		log.DEBUG.Printf("Failed to change mode: %v", err)
		return 0, err
	}

	dir := filepath.Dir(startFile)
	startPath, _ := filepath.Abs(dir)
	file := path.Base(startFile)

	_, lookErr := exec.LookPath(startFile)
	if lookErr != nil {
		log.DEBUG.Printf("Lookerror")
		return 0, lookErr
	}
	env := os.Environ()
	attr := &syscall.ProcAttr{Dir: startPath, Env: env}
	pid, execErr := syscall.ForkExec(file, nil, attr)
	if execErr != nil {
		log.DEBUG.Printf("Exeerror")
		return 0, execErr
	}
	log.DEBUG.Printf("Started process: %d\n", pid)
	return pid, nil
}
Exemplo n.º 4
0
// echoOn turns back on the terminal echo.
func echoOn(fd []uintptr) {
	// Turn on the terminal echo.
	pid, e := syscall.ForkExec(sttyArg0, sttyArgvEOn, &syscall.ProcAttr{Dir: "", Files: fd})
	if e == nil {
		syscall.Wait4(pid, nil, 0, nil)
	}
}
Exemplo n.º 5
0
// execExternal executes an external command.
func (ev *Evaluator) execExternal(fm *form) <-chan *StateUpdate {
	files := make([]uintptr, len(fm.ports))
	for i, port := range fm.ports {
		if port == nil || port.f == nil {
			files[i] = FdNil
		} else {
			files[i] = port.f.Fd()
		}
	}

	args := make([]string, len(fm.args)+1)
	args[0] = fm.Path
	for i, a := range fm.args {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = a.String(ev)
	}

	sys := syscall.SysProcAttr{}
	attr := syscall.ProcAttr{Env: ev.env.Export(), Files: files[:], Sys: &sys}
	pid, err := syscall.ForkExec(fm.Path, args, &attr)
	// Streams are closed after fork-exec of external is complete.
	fm.closePorts(ev)

	update := make(chan *StateUpdate)
	if err != nil {
		update <- &StateUpdate{Terminated: true, Msg: err.Error()}
		close(update)
	} else {
		go waitStateUpdate(pid, update)
	}

	return update
}
Exemplo n.º 6
0
// maybeFork will fork & detach if background is true. First it will rename the out and
// cache dirs so it's safe to run another plz in this repo, then fork & detach child
// processes to do the actual cleaning.
// The parent will then die quietly and the children will continue to actually remove the
// directories.
func maybeFork(outDir, cacheDir string, cleanCache bool) error {
	rm, err := exec.LookPath("rm")
	if err != nil {
		return err
	}
	if !core.PathExists(outDir) || !core.PathExists(cacheDir) {
		return nil
	}
	newOutDir, err := moveDir(outDir)
	if err != nil {
		return err
	}
	args := []string{rm, "-rf", newOutDir}
	if cleanCache {
		newCacheDir, err := moveDir(cacheDir)
		if err != nil {
			return err
		}
		args = append(args, newCacheDir)
	}
	// Note that we can't fork() directly and continue running Go code, but ForkExec() works okay.
	_, err = syscall.ForkExec(rm, args, nil)
	if err == nil {
		// Success if we get here.
		fmt.Println("Cleaning in background; you may continue to do pleasing things in this repo in the meantime.")
		os.Exit(0)
	}
	return err
}
Exemplo n.º 7
0
// 启动子进程执行新程序
func (this *Server) startNewProcess() error {

	listenerFd, err := this.listener.(*Listener).GetFd()
	if err != nil {
		return fmt.Errorf("failed to get socket file descriptor: %v", err)
	}

	path := os.Args[0]

	// 设置标识优雅重启的环境变量
	environList := []string{}
	for _, value := range os.Environ() {
		if value != GRACEFUL_ENVIRON_STRING {
			environList = append(environList, value)
		}
	}
	environList = append(environList, GRACEFUL_ENVIRON_STRING)

	execSpec := &syscall.ProcAttr{
		Env:   environList,
		Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd(), listenerFd},
	}

	fork, err := syscall.ForkExec(path, os.Args, execSpec)
	if err != nil {
		return fmt.Errorf("failed to forkexec: %v", err)
	}

	this.logf("start new process success, pid %d.", fork)

	return nil
}
Exemplo n.º 8
0
// spawn spawns the given filename in background using syscall
func spawn(name string) {
	filepath := path.Join("/init/services", name)

	stdinpath := path.Join("/logs/", name+".stdin")
	stdoutpath := path.Join("/logs/", name+".stdout")
	stderrpath := path.Join("/logs/", name+".stderr")

	os.MkdirAll(path.Dir(stdinpath), 0777)
	os.MkdirAll(path.Dir(stdoutpath), 0777)
	os.MkdirAll(path.Dir(stderrpath), 0777)

	fstdin, err := os.Create(stdinpath)
	if err != nil {
		log.Println("waat", err)
	}
	fstdout, err := os.Create(stdoutpath)
	if err != nil {
		log.Println("waat", err)
	}
	fstderr, err := os.Create(stderrpath)
	if err != nil {
		log.Println("waat", err)
	}

	// Open Files for stdout, stderr
	procAttr := &syscall.ProcAttr{
		Dir:   "/",
		Env:   []string{"MYVAR=345"},
		Files: []uintptr{fstdin.Fd(), fstdout.Fd(), fstderr.Fd()},
		Sys:   nil,
	}

	pid, err := syscall.ForkExec(filepath, nil, procAttr)
	if err != nil {
		log.WithFields(log.Fields{
			"service": filepath,
			"error":   err,
		}).Error("Could not start service.")
	} else {
		log.WithFields(log.Fields{
			"service": filepath,
			"pid":     pid,
		}).Info("Started service succesfully")
	}

	log.Info("Waiting for 3 seconds")
	time.Sleep(3 * time.Second)

	a, err1 := ioutil.ReadFile(stdoutpath)
	b, err2 := ioutil.ReadFile(stderrpath)
	if err1 != nil || err2 != nil {
		log.Error("Could not read", err1, err2)
	} else {
		log.WithFields(log.Fields{
			"service": name,
			"stdout":  string(a),
			"stderr":  string(b),
		}).Info("Service ended.")
	}
}
Exemplo n.º 9
0
func newDirCache(config *core.Configuration) *dirCache {
	cache := new(dirCache)
	// Absolute paths are allowed. Relative paths are interpreted relative to the repo root.
	if config.Cache.Dir[0] == '/' {
		cache.Dir = config.Cache.Dir
	} else {
		cache.Dir = path.Join(core.RepoRoot, config.Cache.Dir)
	}
	// Make directory if it doesn't exist.
	if err := os.MkdirAll(cache.Dir, core.DirPermissions); err != nil {
		panic(fmt.Sprintf("Failed to create root cache directory %s: %s", cache.Dir, err))
	}
	// Fire off the cache cleaner process.
	if config.Cache.DirCacheCleaner != "" && config.Cache.DirCacheCleaner != "none" {
		go func() {
			cleaner := core.ExpandHomePath(config.Cache.DirCacheCleaner)
			log.Info("Running cache cleaner: %s --dir %s --high_water_mark %s --low_water_mark %s",
				cleaner, cache.Dir, config.Cache.DirCacheHighWaterMark, config.Cache.DirCacheLowWaterMark)
			if _, err := syscall.ForkExec(cleaner, []string{
				cleaner,
				"--dir", cache.Dir,
				"--high_water_mark", config.Cache.DirCacheHighWaterMark,
				"--low_water_mark", config.Cache.DirCacheLowWaterMark,
			}, nil); err != nil {
				log.Errorf("Failed to start cache cleaner: %s", err)
			}
		}()
	}
	return cache
}
Exemplo n.º 10
0
func (s *Server) Serve() error {
	log.Debug("this is ddbatman v4")
	s.running = true
	var sessionId int64 = 0
	for s.running {
		select {
		case sessionChan <- sessionId:
			//do nothing
		default:
			//warnning!
			log.Warnf("TASK_CHANNEL is full!")
		}

		conn, err := s.Accept()
		if err != nil {
			log.Warning("accept error %s", err.Error())
			continue
		}
		//allocate a sessionId for a session
		go s.onConn(conn)
		sessionId += 1
	}
	if s.restart == true {
		log.Debug("Begin to restart graceful")
		listenerFile, err := s.listener.(*net.TCPListener).File()
		if err != nil {
			log.Fatal("Fail to get socket file descriptor:", err)
		}
		listenerFd := listenerFile.Fd()

		os.Setenv("_GRACEFUL_RESTART", "true")
		execSpec := &syscall.ProcAttr{
			Env:   os.Environ(),
			Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd(), listenerFd},
		}
		fork, err := syscall.ForkExec(os.Args[0], os.Args, execSpec)
		if err != nil {
			return fmt.Errorf("failed to forkexec: %v", err)
		}

		log.Infof("start new process success, pid %d.", fork)
	}
	timeout := time.NewTimer(time.Minute)
	wait := make(chan struct{})
	go func() {
		s.wg.Wait()
		wait <- struct{}{}
	}()

	select {
	case <-timeout.C:
		log.Error("server : Waittimeout error when close the service")
		return nil
	case <-wait:
		log.Info("server : all goroutine has been done")
		return nil
	}
	return nil
}
Exemplo n.º 11
0
func echoOff(pa syscall.ProcAttr) int {
	pid, err := syscall.ForkExec(sttyCmd, sttyArgvEchoOff, &pa)
	if err != nil {
		fmt.Printf("Error setting echo off: %s\n", err)
	}

	return pid
}
Exemplo n.º 12
0
func echoOn(pa syscall.ProcAttr) {
	pid, err := syscall.ForkExec(sttyCmd, sttyArgvEchoOn, &pa)
	if err == nil {
		syscall.Wait4(pid, &waitStatus, 0, nil)
	} else {
		fmt.Printf("Error setting echo on: %s\n", err)
	}
}
func echoOff(fd []uintptr) (int, error) {
	pid, err := syscall.ForkExec(sttyArg0, sttyArgvEOff, &syscall.ProcAttr{Dir: exec_cwdir, Files: fd})
	if err != nil {
		return 0, fmt.Errorf("failed turning off console echo for password entry:\n{{.ErrorDescription}}", map[string]interface{}{"ErrorDescription": err})
	}

	return pid, nil
}
Exemplo n.º 14
0
// setup and fork/exec myself. Make sure to keep open important FD's that won't get re-created by the child
// specifically, std* and your listen socket
func forker(srv *falcore.Server) (pid int, err int) {
	fmt.Printf("Forking now with socket: %v\n", srv.SocketFd())
	mypath := os.Args[0]
	args := []string{mypath, "-socket", fmt.Sprintf("%v", srv.SocketFd())}
	attr := new(syscall.ProcAttr)
	attr.Files = append([]int(nil), 0, 1, 2, srv.SocketFd())
	pid, err = syscall.ForkExec(mypath, args, attr)
	return
}
Exemplo n.º 15
0
func echoOff(fd []uintptr) (int, error) {
	pid, err := syscall.ForkExec(sttyArg0, sttyArgvEOff, &syscall.ProcAttr{Dir: exec_cwdir, Files: fd})

	if err != nil {
		//Removed error and replaced with nil
		return 0, nil
	}
	return pid, nil
}
Exemplo n.º 16
0
func (pm *ProcessManager) doStart(executablePath string, args []string, procattr *syscall.ProcAttr) {
	var err error
	log.Infof("Getting Ready to start process: %v with args: %v and ProcAttr: %+v", executablePath, args, procattr)
	pm.pid, err = syscall.ForkExec(executablePath, args, procattr)
	if err != nil {
		log.Panicf("Error starting process %v", err)
	} else {
		log.Infof("Process Manager started to manage %v at PID: %v", executablePath, pm.pid)
	}
}
Exemplo n.º 17
0
func forkMyself() error {
	exe, err := platform.Getexe()
	os.Setenv(MAGICENV, Viper.GetString("socket"))
	attr := &syscall.ProcAttr{
		Dir:   "/",
		Env:   os.Environ(),
		Files: []uintptr{0, 1, 2}}
	_, err = syscall.ForkExec(exe, os.Args, attr)
	return err
}
Exemplo n.º 18
0
// Call calls an external command.
func (e ExternalCmd) Call(ec *EvalCtx, argVals []Value, opts map[string]Value) {
	if len(opts) > 0 {
		throw(ErrExternalCmdOpts)
	}
	if util.DontSearch(e.Name) {
		stat, err := os.Stat(e.Name)
		if err == nil && stat.IsDir() {
			// implicit cd
			if len(argVals) > 0 {
				throw(ErrCdNoArg)
			}
			cdInner(e.Name, ec)
			return
		}
	}

	files := make([]uintptr, len(ec.ports))
	for i, port := range ec.ports {
		if port == nil || port.File == nil {
			files[i] = fdNil
		} else {
			files[i] = port.File.Fd()
		}
	}

	args := make([]string, len(argVals)+1)
	for i, a := range argVals {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = ToString(a)
	}

	sys := syscall.SysProcAttr{Setpgid: ec.background}
	attr := syscall.ProcAttr{Env: os.Environ(), Files: files[:], Sys: &sys}

	path, err := ec.Search(e.Name)
	if err != nil {
		throw(err)
	}

	args[0] = path
	pid, err := syscall.ForkExec(path, args, &attr)
	if err != nil {
		throw(errors.New("forkExec: " + err.Error()))
	}

	var ws syscall.WaitStatus
	_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)

	if err != nil {
		throw(fmt.Errorf("wait: %s", err.Error()))
	} else {
		maybeThrow(NewExternalCmdExit(e.Name, ws, pid))
	}
}
Exemplo n.º 19
0
// echoOn turns back on the terminal echo.
func echoOn(fd []uintptr) {
	sttyArg0, sttyErr := getSttyArg0()
	if sttyErr != nil {
		return
	}

	// Turn on the terminal echo.
	pid, e := syscall.ForkExec(sttyArg0, sttyArgvEOn, &syscall.ProcAttr{Dir: "", Files: fd})
	if e == nil {
		syscall.Wait4(pid, &ws, 0, nil)
	}
}
Exemplo n.º 20
0
func spawnServer(cl libkb.CommandLine) (err error) {

	var files []uintptr
	var cmd string
	var args []string
	var devnull, log *os.File
	var pid int

	defer func() {
		if err != nil {
			if devnull != nil {
				devnull.Close()
			}
			if log != nil {
				log.Close()
			}
		}
	}()

	if devnull, err = os.OpenFile("/dev/null", os.O_RDONLY, 0); err != nil {
		return
	}
	files = append(files, devnull.Fd())

	if G.Env.GetSplitLogOutput() {
		files = append(files, uintptr(1), uintptr(2))
	} else {
		if _, log, err = libkb.OpenLogFile(); err != nil {
			return
		}
		files = append(files, log.Fd(), log.Fd())
	}

	attr := syscall.ProcAttr{
		Env:   os.Environ(),
		Sys:   &syscall.SysProcAttr{Setsid: true},
		Files: files,
	}

	cmd, args, err = makeServerCommandLine(cl)
	if err != nil {
		return err
	}

	pid, err = syscall.ForkExec(cmd, args, &attr)
	if err != nil {
		err = fmt.Errorf("Error in ForkExec: %s", err)
	} else {
		G.Log.Info("Forking background server with pid=%d", pid)
	}
	return err
}
func getPassword() string {

	// turn echo off
	var ws syscall.WaitStatus = 0
	idk := &syscall.ProcAttr{Dir: "", Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}}
	if pid, err := syscall.ForkExec("/bin/stty", []string{"stty", "-echo"}, idk); err == nil {
		syscall.Wait4(pid, &ws, 0, nil)
	}

	// read the password
	var password string
	fmt.Print("Enter your password: "******"/bin/stty", []string{"stty", "echo"}, idk); err == nil {
		syscall.Wait4(pid, &ws, 0, nil)
	}

	return password
}
Exemplo n.º 22
0
Arquivo: main.go Projeto: luan/dumb
func main() {
	flag.Parse()
	fmt.Println(os.Args)
	wd, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	fmt.Println("wd:", wd)
	p := "/home/vcap/app/bin/dumb"

	if *numChild > 0 {
		pid, err := syscall.ForkExec(p, []string{p, "-numChild", strconv.Itoa(*numChild - 1)}, &syscall.ProcAttr{
			Env: os.Environ(),
			Dir: wd,
		})

		if err != nil {
			panic(err)
		}
		fmt.Println("i made a first pid! it is:", pid)

		pid, err = syscall.ForkExec(p, []string{p, "-numChild", strconv.Itoa(*numChild - 1)}, &syscall.ProcAttr{
			Env: os.Environ(),
			Dir: wd,
		})

		if err != nil {
			panic(err)
		}
		fmt.Println("i made a second pid! it is:", pid)
	}

	for {
		fmt.Println("heartbeat")
		time.Sleep(time.Second)
	}
}
Exemplo n.º 23
0
func (su *Supervise) Daemon() {
	if su.background {
		su.FlushPid()
		return
	} else if su.daemon {
		os.Setenv("SU_BACKGROUND", "1")
		var procAttr = syscall.ProcAttr{
			su.cwd,
			os.Environ(),
			nil,
			nil,
		}
		syscall.ForkExec(su.exec, os.Args, &procAttr)
		os.Exit(SU_OK)
	}
}
Exemplo n.º 24
0
// Call calls an external command.
func (e ExternalCmd) Call(ec *evalCtx, argVals []Value) {
	if DontSearch(e.Name) {
		stat, err := os.Stat(e.Name)
		if err == nil && stat.IsDir() {
			// implicit cd
			cdInner(e.Name, ec)
		}
	}

	files := make([]uintptr, len(ec.ports))
	for i, port := range ec.ports {
		if port == nil || port.f == nil {
			files[i] = fdNil
		} else {
			files[i] = port.f.Fd()
		}
	}

	args := make([]string, len(argVals)+1)
	for i, a := range argVals {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = ToString(a)
	}

	sys := syscall.SysProcAttr{}
	attr := syscall.ProcAttr{Env: os.Environ(), Files: files[:], Sys: &sys}

	path, err := ec.Search(e.Name)
	if err != nil {
		throw(errors.New("search: " + err.Error()))
	}

	args[0] = path
	pid, err := syscall.ForkExec(path, args, &attr)
	if err != nil {
		throw(errors.New("forkExec: " + err.Error()))
	}

	var ws syscall.WaitStatus
	_, err = syscall.Wait4(pid, &ws, 0, nil)
	if err != nil {
		throw(fmt.Errorf("wait:", err.Error()))
	} else {
		maybeThrow(waitStatusToError(ws))
	}
}
Exemplo n.º 25
0
Arquivo: main.go Projeto: dauwk/pgen
func pwinput(prompt string) (pw string, err error) {
	fmt.Print(prompt)
	cmd := "/bin/stty"
	args := []string{"stty", "-echo"}
	fd := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)}
	proc := new(syscall.ProcAttr)
	proc.Files = fd
	_, err = syscall.ForkExec(cmd, args, proc)
	if err != nil {
		return pw, errors.New("failed forkexec")
	}
	bytes := make([]byte, 1000)
	os.Stdin.Read(bytes)
	pw = strings.TrimRight(string(bytes), string([]byte{0}))
	pw = strings.TrimRight(pw, "\n")
	return
}
Exemplo n.º 26
0
// ForkExec forks the current process and invokes Exec with the file, arguments,
// and environment specified by argv0, argv, and envv.  It returns the process
// id of the forked process and an Error, if any.  The fd array specifies the
// file descriptors to be set up in the new process: fd[0] will be Unix file
// descriptor 0 (standard input), fd[1] descriptor 1, and so on.  A nil entry
// will cause the child to have no open file descriptor with that index.
// If dir is not empty, the child chdirs into the directory before execing the program.
func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []*File) (pid int, err Error) {
	// Create array of integer (system) fds.
	intfd := make([]int, len(fd))
	for i, f := range fd {
		if f == nil {
			intfd[i] = -1
		} else {
			intfd[i] = f.Fd()
		}
	}

	p, e := syscall.ForkExec(argv0, argv, envv, dir, intfd)
	if e != 0 {
		return 0, &PathError{"fork/exec", argv0, Errno(e)}
	}
	return p, nil
}
Exemplo n.º 27
0
func detachCommand(command ...string) {
	sys := syscall.SysProcAttr{}
	files := []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}
	attr := syscall.ProcAttr{
		Env:   os.Environ(),
		Files: files,
		Sys:   &sys,
	}

	pid, err := syscall.ForkExec(command[0], command[1:], &attr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
		return
	}

	closePorts()
	waitPid(pid)
}
Exemplo n.º 28
0
func (su *Supervise) Spawn() {
	var args = make([]string, 3)
	args[0] = "/bin/bash"
	args[1] = "-c"
	args[2] = su.cmd
	var sysProcAttr = syscall.SysProcAttr{}
	sysProcAttr.Setsid = true
	var procAttr = syscall.ProcAttr{
		su.cwd,
		os.Environ(),
		nil,
		&sysProcAttr,
	}
	var pid, _ = syscall.ForkExec("/bin/bash", args, &procAttr)
	su.pid = pid
	su.FlushStatus()
	su.WriteLog("child %d started", su.pid)
}
Exemplo n.º 29
0
// Exec executes an external command.
func (e externalCmd) Exec(ec *evalCtx, argVals []Value) <-chan *stateUpdate {
	files := make([]uintptr, len(ec.ports))
	for i, port := range ec.ports {
		if port == nil || port.f == nil {
			files[i] = fdNil
		} else {
			files[i] = port.f.Fd()
		}
	}

	args := make([]string, len(argVals)+1)
	for i, a := range argVals {
		// NOTE Maybe we should enfore string arguments instead of coercing all
		// args into string
		args[i+1] = toString(a)
	}

	sys := syscall.SysProcAttr{}
	attr := syscall.ProcAttr{Env: os.Environ(), Files: files[:], Sys: &sys}

	path, err := ec.search(e.Name)
	var pid int

	if err == nil {
		args[0] = path
		pid, err = syscall.ForkExec(path, args, &attr)
	}
	// Ports are closed after fork-exec of external is complete.
	ec.closePorts()

	update := make(chan *stateUpdate)
	if err != nil {
		go func() {
			update <- newExitedStateUpdate(newFailure(err.Error()))
			close(update)
		}()
	} else {
		go waitStateUpdate(pid, update)
	}

	return update
}
Exemplo n.º 30
0
// setup and fork/exec myself. Make sure to keep open important FD's that won't get re-created by the child
// specifically, std* and your listen socket
func forker(srv *falcore.Server) (pid int, err error) {
	var socket string
	// At version 1.0.3 the socket FD behavior changed and the fork socket is always 3
	// 0 = stdin, 1 = stdout, 2 = stderr, 3 = acceptor socket
	// This is because the ForkExec dups all the saved FDs down to
	// start at 0.  This is also why you MUST include 0,1,2 in the
	// attr.Files
	if goVersion103OrAbove() {
		socket = "3"
	} else {
		socket = fmt.Sprintf("%v", srv.SocketFd())
	}
	fmt.Printf("Forking now with socket: %v\n", socket)
	mypath := os.Args[0]
	args := []string{mypath, "-socket", socket}
	attr := new(syscall.ProcAttr)
	attr.Files = append([]uintptr(nil), 0, 1, 2, uintptr(srv.SocketFd()))
	pid, err = syscall.ForkExec(mypath, args, attr)
	return
}