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{
cid: id,
id: id,
pid: pid,
bundle: bundle,
stdin: stdin,
stdout: stdout,
@ -55,6 +54,12 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe
relay: pr,
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
process.exit.Store(&processExit{
pid: pid,
@ -62,11 +67,7 @@ func newProcess(ctx context.Context, s *service, id string, pid uint32, pr *pipe
exitedAt: time.Time{},
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
_, eerr := p.Wait()
if eerr != nil {
@ -79,7 +80,7 @@ func waitForProcess(ctx context.Context, process *process, p *os.Process, s *ser
}
now := time.Now()
process.exit.Store(&processExit{
pid: process.pid,
pid: pid,
exitStatus: uint32(status),
exitedAt: now,
exitErr: eerr,
@ -97,7 +98,7 @@ func waitForProcess(ctx context.Context, process *process, p *os.Process, s *ser
&eventstypes.TaskExit{
ContainerID: process.cid,
ID: process.id,
Pid: process.pid,
Pid: pid,
ExitStatus: uint32(status),
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
process.exit.Store(&processExit{
pid: 0, // This is updated when the call to Start happens and the state is overwritten in waitForProcess.
exitStatus: 255,
exitedAt: time.Time{},
exitErr: nil,
@ -129,7 +131,6 @@ type process struct {
cid string
id string
pid uint32
bundle string
stdin string

View File

@ -325,7 +325,7 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
return &taskAPI.StateResponse{
ID: p.id,
Bundle: p.bundle,
Pid: p.pid,
Pid: pe.pid,
Status: status,
Stdin: p.stdin,
Stdout: p.stdout,
@ -667,7 +667,6 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
if err != nil {
return nil, errors.Wrap(err, "failed to find exec process pid")
}
p.pid = uint32(pid)
go waitForProcess(ctx, p, proc, s)
} else {
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)
}
}
stat := p.stat()
return &taskAPI.StartResponse{
Pid: p.pid,
Pid: stat.pid,
}, nil
}
@ -738,7 +738,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
return &taskAPI.DeleteResponse{
ExitedAt: exit.exitedAt,
ExitStatus: exit.exitStatus,
Pid: p.pid,
Pid: exit.pid,
}, nil
}
@ -908,7 +908,7 @@ func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*
return nil, err
}
pid := int(p.pid)
pid := int(p.stat().pid)
opts := runhcs.ResizeTTYOpts{
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) {
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{
ShimPid: uint32(os.Getpid()),
TaskPid: s.processes[s.id].pid,
TaskPid: taskpid,
Version: runhcsShimVersion,
}, nil
}