8000 stage0/status: fix failure when systemd never runs in stage1 by fabiokung · Pull Request #3713 · rkt/rkt · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Feb 24, 2020. It is now read-only.

stage0/status: fix failure when systemd never runs in stage1 #3713

Merged
merged 1 commit into from
Jul 25, 2017
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
4 changes: 4 additions & 0 deletions Documentation/subcommands/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ app-redis=0
app-etcd=0
```

Note that `pid` may not be available shortly after `rkt run`, or `rkt run-prepared`, even when `state=running`.

The `--wait` flags below can be used to wait for a Pod to be running with its pid captured.

If the pod is still running, you can wait for it to finish and then get the status with `rkt status --wait UUID`.
To wait for the pod to become ready, execute `rkt status --wait-ready`.
Both options also accept a duration. To wait up to 10 seconds until the pod is finished, execute `rkt status --wait=10s UUID`.
Expand Down
46 changes: 16 additions & 30 deletions rkt/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,38 +203,24 @@ func printStatus(p *pkgPod.Pod) error {
stdout.Printf("networks=%s", fmtNets(p.Nets))
}

if state == pkgPod.Running || state == pkgPod.Deleting || state == pkgPod.ExitedDeleting || state == pkgPod.Exited || state == pkgPod.ExitedGarbage {
var pid int
pidCh := make(chan int, 1)

// Wait slightly because the pid file might not be written yet when the state changes to 'Running'.
go func() {
for {
pid, err := p.Pid()
if err == nil {
pidCh <- pid
return
}
time.Sleep(time.Millisecond * 100)
}
}()

select {
case pid = <-pidCh:
case <-time.After(time.Second):
return fmt.Errorf("unable to get PID for pod %q: %v", p.UUID, err)
}
if !(state == pkgPod.Running || state == pkgPod.Deleting || state == pkgPod.ExitedDeleting || state == pkgPod.Exited || state == pkgPod.ExitedGarbage) {
return nil
}

stdout.Printf("pid=%d\nexited=%t", pid, (state == pkgPod.Exited || state == pkgPod.ExitedGarbage))
if pid, err := p.Pid(); err == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change may re-introduce the race documented in the comment below, which was previously addressed by the goroutine+timeout. I would suggest to special-case the running case, block on it until pid exists or we hit the timeout, and then proceed with your logic.

// the pid file might not be written yet when the state changes to 'Running'
// it may also never be written if systemd never executes (e.g.: a bad command)
stdout.Printf("pid=%d", pid)
}
stdout.Printf("exited=%t", (state == pkgPod.Exited || state == pkgPod.ExitedGarbage))

if state != pkgPod.Running {
stats, err := getExitStatuses(p)
if err != nil {
return fmt.Errorf("unable to get exit statuses for pod %q: %v", p.UUID, err)
}
for app, stat := range stats {
stdout.Printf("app-%s=%d", app, stat)
}
if state != pkgPod.Running {
stats, err := getExitStatuses(p)
if err != nil {
return fmt.Errorf("unable to get exit statuses for pod %q: %v", p.UUID, err)
}
for app, stat := range stats {
stdout.Printf("app-%s=%d", app, stat)
}
}
return nil
Expand Down
0