func (s *SlaveNode) doUnbootedState(monitor *SlaveMonitor) string {  
	if s.Parent == nil {
		s.L.Lock()
		parts := strings.Split(monitor.tree.ExecCommand, " ")
		cmd := exec.Command(parts[0], parts[1:]...)
		file := monitor.remoteMasterFile
		cmd.Env = append(os.Environ(), fmt.Sprintf("ZEUS_MASTER_FD=%d", file.Fd()))
		cmd.ExtraFiles = []*os.File{file}
		go s.babysitRootProcess(cmd)
		s.L.Unlock()
	} else {
		s.Parent.RequestSlaveBoot(s)
	}
	<-s.event  
	s.L.Lock()
	defer s.L.Unlock()
	if s.Error != "" {
		return SCrashed
	}
	return SBooting
}
These "doXState" functions are called when a SlaveNode enters a state. They are expected
to continue to execute until
"SUnbooted" represents the state where we do not yet have the PID
of a process to use for *this* node. In this state, we wait for the
parent process to spawn a process for us and hear back from the
SlaveMonitor.
package processtree
import (
	"bufio"
	"math/rand"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
	"fmt"
	"runtime"
	"github.com/burke/zeus/go/filemonitor"
	"github.com/burke/zeus/go/messages"
	slog "github.com/burke/zeus/go/shinylog"
	"github.com/burke/zeus/go/unixsocket"
)
const (
	forceKillTimeout = time.Second
)
type SlaveNode struct {
	ProcessTreeNode
	socket      *unixsocket.Usock
	pid         int
	Error       string
	Slaves      []*SlaveNode
	Commands    []*CommandNode
	fileMonitor filemonitor.FileMonitor
	hasSuccessfullyBooted bool
	needsRestart        chan bool
	commandBootRequests chan *CommandRequest
	slaveBootRequests   chan *SlaveNode
	L        sync.Mutex
	features map[string]bool
	featureL sync.Mutex
	state    string
	event chan bool
}
type CommandReply struct {
	State string
	File  *os.File
}
type CommandRequest struct {
	Name    string
	Retchan chan *CommandReply
}
const (
	SUnbooted = "U"
	SBooting  = "B"
	SReady    = "R"
	SCrashed  = "C"
)
var humanreadableStates = map[string]string{
	SUnbooted: "unbooted",
	SBooting:  "booted",
	SReady:    "ready",
	SCrashed:  "crashed",
}
func (tree *ProcessTree) NewSlaveNode(identifier string, parent *SlaveNode, monitor filemonitor.FileMonitor) *SlaveNode {
	s := SlaveNode{}
	s.needsRestart = make(chan bool, 1)
	s.slaveBootRequests = make(chan *SlaveNode, 256)
	s.commandBootRequests = make(chan *CommandRequest, 256)
	s.features = make(map[string]bool)
	s.event = make(chan bool)
	s.Name = identifier
	s.Parent = parent
	s.fileMonitor = monitor
	tree.SlavesByName[identifier] = &s
	return &s
}
func (s *SlaveNode) RequestRestart() {
	s.L.Lock()
	defer s.L.Unlock()
	if s.ReportBootEvent() {
		s.Error = "Received restart request while booting"
	}
	select {
	case s.needsRestart <- true:
	default:
	}
}
func (s *SlaveNode) RequestSlaveBoot(slave *SlaveNode) {
	s.slaveBootRequests <- slave
}
func (s *SlaveNode) RequestCommandBoot(request *CommandRequest) {
	s.commandBootRequests <- request
}
func (s *SlaveNode) ReportBootEvent() bool {
	select {
	case s.event <- true:
		return true
	default:
		return false
	}
}
func (s *SlaveNode) SlaveWasInitialized(pid, parentPid int, usock *unixsocket.Usock, featurePipeFd int) {
	file := os.NewFile(uintptr(featurePipeFd), "featurepipe")
	s.L.Lock()
	if !s.ReportBootEvent() {
		s.forceKillPid(pid)
		s.trace("Unexpected process %d with parent %d for slave %q was killed", pid, parentPid, s.Name)
	} else {
		s.wipe()
		s.pid = pid
		s.socket = usock
		go s.handleMessages(file)
		s.trace("initialized slave %s with pid %d from parent %d", s.Name, pid, parentPid)
	}
	s.L.Unlock()
}
func (s *SlaveNode) Run(monitor *SlaveMonitor) {
	nextState := SUnbooted
	for {
		s.L.Lock()
		s.state = nextState
		s.L.Unlock()
		monitor.tree.StateChanged <- true
		switch nextState {
		case SUnbooted:
			s.trace("entering state SUnbooted")
			nextState = s.doUnbootedState(monitor)
		case SBooting:
			s.trace("entering state SBooting")
			nextState = s.doBootingState()
		case SReady:
			s.trace("entering state SReady")
			nextState = s.doReadyState()
		case SCrashed:
			s.trace("entering state SCrashed")
			nextState = s.doCrashedState()
		default:
			slog.FatalErrorString("Unrecognized state: " + nextState)
		}
	}
}
func (s *SlaveNode) State() string {
	s.L.Lock()
	defer s.L.Unlock()
	return s.state
}
func (s *SlaveNode) HumanReadableState() string {
	return humanreadableStates[s.state]
}
func (s *SlaveNode) HasFeature(file string) bool {
	s.featureL.Lock()
	defer s.featureL.Unlock()
	return s.features[file]
}