Fixes a bug in runhcs shim Exec.Pid

When an exec occurs the pid was not properly updated on the in memory state
value causing many queries to see a 0.

Signed-off-by: Justin Terry (VM) <juterry@microsoft.com>
This commit is contained in:
Justin Terry (VM) 2019-01-14 13:09:21 -08:00
parent adfaa697a8
commit bcd4cc51c8
2 changed files with 21 additions and 14 deletions

View File

@ -46,7 +46,6 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe
process := &process{ process := &process{
cid: id, cid: id,
id: id, id: id,
pid: pid,
bundle: bundle, bundle: bundle,
stdin: stdin, stdin: stdin,
stdout: stdout, stdout: stdout,
@ -55,6 +54,12 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe
relay: pr, relay: pr,
waitBlock: make(chan struct{}), waitBlock: make(chan struct{}),
} }
go waitForProcess(ctx, process, p, s)
return process, nil
}
func waitForProcess(ctx context.Context, process *process, p *os.Process, s *service) {
pid := uint32(p.Pid)
// Store the default non-exited value for calls to stat // Store the default non-exited value for calls to stat
process.exit.Store(&processExit{ process.exit.Store(&processExit{
pid: pid, pid: pid,
@ -62,11 +67,7 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe
exitedAt: time.Time{}, exitedAt: time.Time{},
exitErr: nil, exitErr: nil,
}) })
go waitForProcess(ctx, process, p, s)
return process, nil
}
func waitForProcess(ctx context.Context, process *process, p *os.Process, s *service) {
var status int var status int
_, eerr := p.Wait() _, eerr := p.Wait()
if eerr != nil { if eerr != nil {
@ -79,7 +80,7 @@ func waitForProcess(ctx context.Context, process *process, p *os.Process, s *ser
} }
now := time.Now() now := time.Now()
process.exit.Store(&processExit{ process.exit.Store(&processExit{
pid: process.pid, pid: pid,
exitStatus: uint32(status), exitStatus: uint32(status),
exitedAt: now, exitedAt: now,
exitErr: eerr, exitErr: eerr,
@ -97,7 +98,7 @@ func waitForProcess(ctx context.Context, process *process, p *os.Process, s *ser
&eventstypes.TaskExit{ &eventstypes.TaskExit{
ContainerID: process.cid, ContainerID: process.cid,
ID: process.id, ID: process.id,
Pid: process.pid, Pid: pid,
ExitStatus: uint32(status), ExitStatus: uint32(status),
ExitedAt: now, ExitedAt: now,
}) })
@ -117,6 +118,7 @@ func newExecProcess(ctx context.Context, s *service, cid, id string, pr *pipeRel
} }
// Store the default non-exited value for calls to stat // Store the default non-exited value for calls to stat
process.exit.Store(&processExit{ process.exit.Store(&processExit{
pid: 0, // This is updated when the call to Start happens and the state is overwritten in waitForProcess.
exitStatus: 255, exitStatus: 255,
exitedAt: time.Time{}, exitedAt: time.Time{},
exitErr: nil, exitErr: nil,
@ -129,7 +131,6 @@ type process struct {
cid string cid string
id string id string
pid uint32
bundle string bundle string
stdin string stdin string

View File

@ -325,7 +325,7 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
return &taskAPI.StateResponse{ return &taskAPI.StateResponse{
ID: p.id, ID: p.id,
Bundle: p.bundle, Bundle: p.bundle,
Pid: p.pid, Pid: pe.pid,
Status: status, Status: status,
Stdin: p.stdin, Stdin: p.stdin,
Stdout: p.stdout, Stdout: p.stdout,
@ -667,7 +667,6 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to find exec process pid") return nil, errors.Wrap(err, "failed to find exec process pid")
} }
p.pid = uint32(pid)
go waitForProcess(ctx, p, proc, s) go waitForProcess(ctx, p, proc, s)
} else { } else {
if err := rhcs.Start(ctx, p.id); err != nil { if err := rhcs.Start(ctx, p.id); err != nil {
@ -697,8 +696,9 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
} }
stat := p.stat()
return &taskAPI.StartResponse{ return &taskAPI.StartResponse{
Pid: p.pid, Pid: stat.pid,
}, nil }, nil
} }
@ -738,7 +738,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
return &taskAPI.DeleteResponse{ return &taskAPI.DeleteResponse{
ExitedAt: exit.exitedAt, ExitedAt: exit.exitedAt,
ExitStatus: exit.exitStatus, ExitStatus: exit.exitStatus,
Pid: p.pid, Pid: exit.pid,
}, nil }, nil
} }
@ -908,7 +908,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
return nil, err return nil, err
} }
pid := int(p.pid) pid := int(p.stat().pid)
opts := runhcs.ResizeTTYOpts{ opts := runhcs.ResizeTTYOpts{
Pid: &pid, Pid: &pid,
} }
@ -967,9 +967,15 @@ func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.
func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) { func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*taskAPI.ConnectResponse, error) {
log.G(ctx).Debugf("Connect: %s", r.ID) log.G(ctx).Debugf("Connect: %s", r.ID)
var taskpid uint32
p, _ := s.getProcess(r.ID, "")
if p != nil {
taskpid = p.stat().pid
}
return &taskAPI.ConnectResponse{ return &taskAPI.ConnectResponse{
ShimPid: uint32(os.Getpid()), ShimPid: uint32(os.Getpid()),
TaskPid: s.processes[s.id].pid, TaskPid: taskpid,
Version: runhcsShimVersion, Version: runhcsShimVersion,
}, nil }, nil
} }