-
Notifications
You must be signed in to change notification settings - Fork 41
Conversation
@jterry75, |
I have verified this through docker for both the init process and an exec process such as VI that the console resize is indeed happening. |
What happens if the TTY relay finishes and closes master just as the resize console call is coming down? It seems like some synchronization might be missing there. |
I certainly could add synchronization but I didn't for two reasons.
All that said I am happy to add a mutex on the relay that exposes the console handle. Let me know if you still want it. |
The kernel is not a safe form of synchronization. The fd can get reused right after the close call, so you will send the ioctl to the wrong place. Why can't the relay implement the resize method? Then you can synchronize internally without exposing a mutex. |
a57d421
to
7026cdf
Compare
service/gcs/core/gcs/gcs.go
Outdated
if !ok { | ||
entry, ok = c.externalProcessCache[pid] | ||
if !ok { | ||
if id == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually expect the HCS to send an empty containerID string for external processes? I didn't know about this behavior, just making sure this is something we can definitely rely on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ContainerID is not a required field. The HCS will not send any parameter and the unmarshal call from json will default "". I could be wrong but this seems safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -106,7 +115,7 @@ func (c *MockCore) SignalContainer(id string, signal oslayer.Signal) error { | |||
} | |||
|
|||
// SignalProcess captures its arguments and returns a nil error. | |||
func (c *MockCore) SignalProcess(pid int, options prot.SignalProcessOptions) error { | |||
func (c *MockCore) SignalProcess(id string, pid int, options prot.SignalProcessOptions) error { | |||
c.LastSignalProcess = SignalProcessCall{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ID field to SignalProcessCall
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And update tests to match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
@@ -159,11 +168,23 @@ func (c *MockCore) RegisterContainerExitHook(id string, exitHook func(oslayer.Pr | |||
|
|||
// RegisterProcessExitHook captures its arguments, runs the given exit hook on | |||
// a process exit state with exit code 103, and returns a nil error. | |||
func (c *MockCore) RegisterProcessExitHook(pid int, exitHook func(oslayer.ProcessExitState)) error { | |||
func (c *MockCore) RegisterProcessExitHook(id string, pid int, exitHook func(oslayer.ProcessExitState)) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ID field to RegisterProcessExitHookCall
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And update tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
service/gcs/runtime/runc/runc.go
Outdated
@@ -528,8 +536,8 @@ func (c *container) startProcess(tempProcessDir string, hasTerminal bool, stdioS | |||
} | |||
|
|||
var relay *stdio.TtyRelay | |||
var master *os.File |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm probably missing something, but why move this to a higher scope?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was a remnant before we used the TtyRelay to do the work. Put back now.
service/gcs/stdio/stdio.go
Outdated
|
||
"github.com/Microsoft/opengcs/service/gcs/transport" | ||
"github.com/Sirupsen/logrus" | ||
"github.com/pkg/errors" | ||
|
||
"golang.org/x/sys/unix" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: To keep with the pattern we've started following (using goimports to perform formatting), this import should probably go with the above github.com imports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
7026cdf
to
b055df3
Compare
service/gcs/stdio/stdio.go
Outdated
return errors.New("error resizing console pty is closed") | ||
} | ||
|
||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, r.pty.Fd(), uintptr(unix.TIOCSWINSZ), uintptr(unsafe.Pointer(&consoleSize{Height: height, Width: width}))); err != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Syscall [](start = 25, length = 7)
Probably you should make a standalone function in tty.go that calls this IOCTL that can be used or tested separately from the relay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
service/gcs/stdio/stdio.go
Outdated
// small window that ResizeConsole could still get an invalid Fd. We call wait again to | ||
// enusure that no ResizeConsole call came in before actualling closing the pty. | ||
atomic.StoreInt32(&r.closing, 1) | ||
r.wg.Wait() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wg [](start = 3, length = 2)
I think you need to use a separate mutex unfortunately; according to the docs, you can't legally increment the wait group once Wait has been called:
go doc sync.WaitGroup.Add
func (wg *WaitGroup) Add(delta int)
Add adds delta, which may be negative, to the WaitGroup counter. If the
counter becomes zero, all goroutines blocked on Wait are released. If the
counter goes negative, Add panics.
Note that calls with a positive delta that occur when the counter is zero
must happen before a Wait. Calls with a negative delta, or calls with a
positive delta that start when the counter is greater than zero, may happen
at any time. Typically this means the calls to Add should execute before the
statement creating the goroutine or other event to be waited for. If a
WaitGroup is reused to wait for several independent sets of events, new Add
calls must happen after all previous Wait calls have returned. See the
WaitGroup example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
service/gcs/stdio/stdio.go
Outdated
|
||
// ResizeConsole sends the appropriate resize to a pTTY FD | ||
// Synchronization of pty should be handled in the callers context. | ||
func ResizeConsole(pty *os.File, height, width uint16) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ResizeConsole [](start = 5, length = 13)
put this in tty.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
service/gcs/stdio/stdio.go
Outdated
|
||
if pty == nil { | ||
return errors.New("error resizing console for nil pty fd") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
service/gcs/core/gcs/gcs.go
Outdated
containerEntry.ExitStatus = state | ||
for _, hook := range containerEntry.ExitHooks { | ||
hook(state) | ||
} | ||
delete(c.containerCache, id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why get rid of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a mistake for sure. Not sure how I missed that
e7abf55
to
b3eb8d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! I just have two more quick suggestions!
service/gcs/bridge/bridge_test.go
Outdated
It("should receive the correct values", func() { | ||
Expect(callArgs.Pid).To(Equal(102)) | ||
Expect(callArgs.Height).To(Equal(uint16(80))) | ||
Expect(callArgs.Width).To(Equal(uint16(80))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, forgot to mention this on my last review: If we're getting rid of the id==""
check in this PR, we should probably get rid of this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
service/gcs/stdio/stdio.go
Outdated
r.s.Close() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: unnecessary newline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed.
b3eb8d7
to
37ae80c
Compare
service/gcs/core/gcs/gcs.go
Outdated
// entry. | ||
processCache map[int]*processCacheEntry | ||
|
||
externalProcessCacheMutex sync.RWMutex | ||
// externalProcessCache stores information about external processes which |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
externalProcessCache [](start = 4, length = 20)
comment needs updating
@@ -43,6 +43,7 @@ type Process interface { | |||
Wait() (oslayer.ProcessExitState, error) | |||
Pid() int | |||
Delete() error | |||
Tty() *stdio.TtyRelay |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tty [](start = 1, length = 3)
Maybe better to just expose the Resize method directly here? This seems to leak an implementation detail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will open an issue to unify the runtime Process and the oslayer Process interfaces. The issue is that for container/external processes we store them quite differently and the cache cant support both. We really should be thinking about them the same with a single Process interface from the GCS perspective. Will this work for now?
🕐 |
Removes the per container cache for processes as they are all external pid's Changes to use a mutex instead of the wait group for ResizeConsole so we are confident of order. Puts back some of the containerID overloads because HCS always sends this even for external processes.
37ae80c
to
32fdcad
Compare
Anymore feedback here? Would like to get this checked in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
Resolves: #76