mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-04 23:17:50 +00:00
Improve terminal reuse and attach
Currently attach and the editor do not share the same logic for saving and restoring the terminal, and are not suitable for nesting (when the caller wants to create something, attach, and then delete something when the attach is over). This commit moves the interrupt protection logic to a util package and supports nesting interrupt handlers.
This commit is contained in:
@@ -23,13 +23,13 @@ import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/term"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -125,7 +125,7 @@ func (e Editor) Launch(path string) error {
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
glog.V(5).Infof("Opening file with editor %v", args)
|
||||
if err := withSafeTTYAndInterrupts(cmd.Run); err != nil {
|
||||
if err := (term.TTY{In: os.Stdin, TryDev: true}).Safe(cmd.Run); err != nil {
|
||||
if err, ok := err.(*exec.Error); ok {
|
||||
if err.Err == exec.ErrNotFound {
|
||||
return fmt.Errorf("unable to launch the editor %q", strings.Join(e.Args, " "))
|
||||
@@ -160,40 +160,6 @@ func (e Editor) LaunchTempFile(prefix, suffix string, r io.Reader) ([]byte, stri
|
||||
return bytes, path, err
|
||||
}
|
||||
|
||||
// withSafeTTYAndInterrupts invokes the provided function after the terminal
|
||||
// state has been stored, and then on any error or termination attempts to
|
||||
// restore the terminal state to its prior behavior. It also eats signals
|
||||
// for the duration of the function.
|
||||
func withSafeTTYAndInterrupts(fn func() error) error {
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, childSignals...)
|
||||
defer signal.Stop(ch)
|
||||
|
||||
inFd := os.Stdin.Fd()
|
||||
if !term.IsTerminal(inFd) {
|
||||
if f, err := os.Open("/dev/tty"); err == nil {
|
||||
defer f.Close()
|
||||
inFd = f.Fd()
|
||||
}
|
||||
}
|
||||
|
||||
if term.IsTerminal(inFd) {
|
||||
state, err := term.SaveState(inFd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
if _, ok := <-ch; !ok {
|
||||
return
|
||||
}
|
||||
term.RestoreTerminal(inFd, state)
|
||||
}()
|
||||
defer term.RestoreTerminal(inFd, state)
|
||||
return fn()
|
||||
}
|
||||
return fn()
|
||||
}
|
||||
|
||||
func tempFile(prefix, suffix string) (f *os.File, err error) {
|
||||
dir := os.TempDir()
|
||||
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package editor
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// childSignals are the allowed signals that can be sent to children in Unix variant OS's
|
||||
var childSignals = []os.Signal{syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT}
|
||||
@@ -1,26 +0,0 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package editor
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// childSignals are the allowed signals that can be sent to children in Windows to terminate
|
||||
var childSignals = []os.Signal{os.Interrupt}
|
||||
Reference in New Issue
Block a user