Skip to content

Add conpty (pseudo console) package#1228

Merged
dcantah merged 4 commits into
microsoft:masterfrom
dcantah:conpty
Dec 15, 2021
Merged

Add conpty (pseudo console) package#1228
dcantah merged 4 commits into
microsoft:masterfrom
dcantah:conpty

Conversation

@dcantah

@dcantah dcantah commented Nov 16, 2021

Copy link
Copy Markdown
Contributor

This change adds a conpty package (and necessary bindings) that houses go friendly wrappers around
the Pseudo Console API in Windows. This will be used to support tty scenarios for Host Process containers.

There's not many tests I can add here as you need to hook this up to a running
process, where that work is coming soon. I've included a video of this working below using the
new process execution package I've been working on.

conpty.mp4

Code for the demo for a sneak peak at the API:

package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"os"
	"syscall"

	"github.com/Microsoft/hcsshim/internal/conpty"
	"github.com/Microsoft/hcsshim/internal/exec"
	"github.com/Microsoft/hcsshim/internal/jobobject"
	"github.com/containerd/console"
)

type rawConReader struct {
	f *os.File
}

func (r rawConReader) Read(b []byte) (int, error) {
	n, err := syscall.Read(syscall.Handle(r.f.Fd()), b)
	if n == 0 && len(b) != 0 && err == nil {
		// A zero-byte read on a console indicates that the user wrote Ctrl-Z.
		b[0] = 26
		return 1, nil
	}
	return n, err
}

func main() {
	cpty, err := conpty.New(80, 20, 0)
	if err != nil {
		log.Fatal(err)
	}
	defer cpty.Close()

	job, err := jobobject.Create(context.Background(), &jobobject.Options{Name: "test"})
	if err != nil {
		log.Fatal(err)
	}
	defer job.Close()

	e, err := exec.New(
		`C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe`,
		"powershell",
		exec.WithJobObject(job),
		exec.WithConPty(cpty),
		exec.WithDir("C:\\"),
		exec.WithEnv(os.Environ()),
	)
	if err != nil {
		log.Fatal(err)
	}

	err = e.Start()
	if err != nil {
		log.Fatalf("failed to start process: %v", err)
	}

	var osStdin io.Reader = os.Stdin
	con, err := console.ConsoleFromFile(os.Stdin)
	if err == nil {
		err = con.SetRaw()
		if err != nil {
			log.Fatal(err)
		}
		defer func() {
			_ = con.Reset()
		}()
		// Console reads return EOF whenever the user presses Ctrl-Z.
		// Wrap the reads to translate these EOFs back.
		osStdin = rawConReader{os.Stdin}
	}

	go func() {
		_, _ = io.Copy(os.Stdout, cpty.OutPipe())
	}()

	go func() {
		_, _ = io.Copy(cpty.InPipe(), osStdin)
	}()

	err = e.Wait()
	if err != nil {
		log.Fatalf("error waiting for process: %v", err)
	}
	fmt.Printf("exit code was: %d\n", e.ExitCode())
}

@dcantah dcantah requested a review from a team as a code owner November 16, 2021 05:00
@dcantah dcantah force-pushed the conpty branch 2 times, most recently from 1738766 to 1d2b761 Compare November 16, 2021 05:13
@dcantah

dcantah commented Nov 16, 2021

Copy link
Copy Markdown
Contributor Author

fyi @jsturtevant @marosset

Comment thread internal/conpty/conpty.go Outdated
Comment thread internal/winapi/process.go
This change adds a conpty package that houses go friendly wrappers around
the Pseudo Console API in Windows. This will be used to support tty scenarios
for Host Process containers.

There's not many tests I can add here as you need to hook this up to a running
process, where that work is coming.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
Comment thread internal/winapi/process.go Outdated
Comment thread internal/conpty/conpty.go Outdated
Comment thread internal/conpty/conpty.go Outdated
Comment thread internal/conpty/conpty.go
* CPty -> ConPTY
* Unexport InitializeProcThreadAttributeList

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
Signed-off-by: Daniel Canter <dcanter@microsoft.com>
The issue with x/sys/windows is being solved here
https://go-review.googlesource.com/c/sys/+/371276/1/windows/exec_windows.go#153.
This change adds a comment to state that we'll swap once the fix is in.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>

@anmaxvl anmaxvl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

small nit, otherwise LGTM

Comment thread internal/winapi/process.go
Comment thread internal/winapi/zsyscall_windows.go
@dcantah dcantah merged commit f8cbd0b into microsoft:master Dec 15, 2021
dcantah added a commit to dcantah/hcsshim that referenced this pull request Jan 4, 2022
* Add conpty (pseudo console) package

This change adds a conpty package that houses go friendly wrappers around
the Pseudo Console API in Windows. This will be used to support tty scenarios
for Host Process containers.

There's not many tests I can add here as you need to hook this up to a running
process, where that work is coming.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
(cherry picked from commit f8cbd0b)
Signed-off-by: Daniel Canter <dcanter@microsoft.com>
dcantah added a commit to dcantah/hcsshim that referenced this pull request Jan 4, 2022
* Add conpty (pseudo console) package

This change adds a conpty package that houses go friendly wrappers around
the Pseudo Console API in Windows. This will be used to support tty scenarios
for Host Process containers.

There's not many tests I can add here as you need to hook this up to a running
process, where that work is coming.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
(cherry picked from commit f8cbd0b)
Signed-off-by: Daniel Canter <dcanter@microsoft.com>
princepereira pushed a commit to princepereira/hcsshim that referenced this pull request Aug 29, 2024
* Add conpty (pseudo console) package

This change adds a conpty package that houses go friendly wrappers around
the Pseudo Console API in Windows. This will be used to support tty scenarios
for Host Process containers.

There's not many tests I can add here as you need to hook this up to a running
process, where that work is coming.

Signed-off-by: Daniel Canter <dcanter@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants