// In "SBooting", we have a pid and socket to the process we will use, // but it has not yet finished initializing (generally, running the code // specific to this slave. When we receive a message about the success or // failure of this operation, we transition to either crashed or ready. func (s *SlaveNode) doBootingState() string { // -> {SCrashed, SReady} // The slave will execute its action and respond with a status... // Note we don't hold the mutex while waiting for the action to execute. msg, err := s.socket.ReadMessage() if err != nil { slog.Error(err) } s.L.Lock() defer s.L.Unlock() msg, err = messages.ParseActionResponseMessage(msg) if err != nil { slog.ErrorString("[" + s.Name + "] " + err.Error()) } if msg == "OK" { return SReady } if s.Pid > 0 { syscall.Kill(s.Pid, syscall.SIGKILL) } s.wipe() s.Error = msg return SCrashed }
// In "SBooting", we have a pid and socket to the process we will use, // but it has not yet finished initializing (generally, running the code // specific to this slave. When we receive a message about the success or // failure of this operation, we transition to either crashed or ready. func (s *SlaveNode) doBootingState() string { // -> {SCrashed, SReady} // The slave will execute its action and respond with a status... // Note we don't hold the mutex while waiting for the action to execute. msg, err := s.socket.ReadMessage() if err != nil { slog.Error(err) } s.trace("in booting state") s.L.Lock() defer s.L.Unlock() msg, err = messages.ParseActionResponseMessage(msg) if err != nil { slog.ErrorString("[" + s.Name + "] " + err.Error()) } if msg == "OK" { return SReady } // Drain the process's feature messages, if we have any, so // that reloads happen when any load-time problems get fixed: s.L.Unlock() s.handleMessages() s.L.Lock() // Clean up: if s.Pid > 0 { syscall.Kill(s.Pid, syscall.SIGKILL) } s.wipe() s.Error = msg return SCrashed }