Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions cmd/svcinit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,17 +285,16 @@ func main() {

testCancel()

// TODO(zbarsky): what is the right behavior here when services are crashing in ibazel mode?

// This is a brittle way of draining a channel in a nonblocking way,
// consider instead signalling cancellation of the services with a
// context, letting them close the channel, and using a waitgroup to
// wait for them to exit.
// This is a brittle way of draining a channel in a nonblocking way,
// consider instead signalling cancellation of the services with a
// context, letting them close the channel, and using a waitgroup to
// wait for them to exit.
// See: https://github.com/hermeticbuild/rules_itest/issues/72
Drain:
for {
select {
case <-servicesErrCh:
// nothing
case crashErr := <-servicesErrCh:
log.Printf("Discarding pending service error before reload: %v", crashErr)
default:
break Drain
}
Expand Down
16 changes: 14 additions & 2 deletions runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"reflect"
"runtime"
"sync"
"syscall"
"time"

"rules_itest/logger"
Expand Down Expand Up @@ -198,9 +199,20 @@ func (r *Runner) UpdateSpecs(serviceSpecs ServiceSpecs, ibazelCmd []byte) error
}

for _, label := range updateActions.toReloadLabels {
_, err := r.serviceInstances[label].stdin.Write(ibazelCmd)
old := r.serviceInstances[label]
_, err := old.stdin.Write(ibazelCmd)
if err != nil {
return err
// Service likely crashed — fall back to a full restart.
log.Printf("%s hot-reload stdin write failed, falling back to restart: %v", colorize(old.VersionedServiceSpec), err)
old.stdin.Close()
if stopErr := old.StopWithSignal(syscall.SIGKILL); stopErr != nil {
log.Printf("%s stop during crash fallback failed: %v", colorize(old.VersionedServiceSpec), stopErr)
}
delete(r.serviceInstances, label)
r.serviceInstances[label], err = prepareServiceInstance(r.ctx, serviceSpecs[label])
if err != nil {
return err
}
}
}

Expand Down
6 changes: 4 additions & 2 deletions runner/service_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,10 @@ func (s *ServiceInstance) StopWithSignal(signal syscall.Signal) error {
s.killed = true
}()

if err != nil {
return err
// If the process has already exited (raced between killGroup above and here),
// return nil — the killGroup call above already attempted group cleanup.
if s.isDone() {
Comment thread
jaqx0r marked this conversation as resolved.
return nil
Comment thread
jaqx0r marked this conversation as resolved.
}

if signal == syscall.SIGKILL {
Expand Down
Loading