Skip to content

Conversation

@rgarcia
Copy link
Contributor

@rgarcia rgarcia commented Nov 11, 2025

using the same approach that docker exec ... uses:

  • allow for allocating a tty when making a process
  • expose an http endpoint that is hijack-able to do pure tcp stuff

./cmd/shell contains a proof of concept for what would eventually land in the kernel CLI.

demo running against the image running in unikraft:

https://screen.studio/share/6imUEYCv


Note

Implements interactive PTY support for spawned processes and an attach/resize workflow, plus a small CLI demo and minor wrapper tweaks.

  • Extends ProcessSpawnRequest with allocate_tty, rows, cols; server spawns PTY-backed cmds via creack/pty, tracks ptyFile/isTTY, and defers pipe readers in PTY mode
  • Adds raw attach endpoint GET /process/{process_id}/attach (HTTP hijack) and POST /process/{process_id}/resize; enforces single active attach and uses poll-based PTY→conn copy; cleans up FDs and retains process status briefly post-exit
  • Updates OpenAPI (openapi.yaml) and generated client/server (lib/oapi) to include PTY fields and processResize; adds deps creack/pty, x/sys, x/term
  • New cmd/shell PoC: spawns /bin/bash with TTY, hijacks attach over TCP/TLS, resizes on SIGWINCH
  • Wrapper scripts: ensure/export a sane HOSTNAME early in headful/headless images

Written by Cursor Bugbot for commit 7d47214. This will update automatically on new commits. Configure here.

@rgarcia rgarcia requested review from Sayan- and hiroTamada November 11, 2025 22:00
@mesa-dot-dev
Copy link

mesa-dot-dev bot commented Nov 11, 2025

Mesa Description

using the same approach that docker exec ... uses:

  • allow for allocating a tty when making a process
  • expose an http endpoint that is hijack-able to do pure tcp stuff

./cmd/shell contains a proof of concept for what would eventually land in the kernel CLI.

demo running against the image running in unikraft:

https://screen.studio/share/6imUEYCv


Note

This PR adds the ability to spawn processes with a pseudo-terminal (PTY) and attach to them for interactive sessions, similar to docker exec.

  • API & Process Management:
    • POST /process/spawn is extended to support TTY allocation with initial dimensions.
    • A new GET /process/{process_id}/attach endpoint uses an HTTP hijack to provide a raw TCP stream for PTY interaction.
    • A new POST /process/{process_id}/resize endpoint allows for resizing the PTY window.
  • Proof-of-Concept Shell:
    • A new server/cmd/shell command demonstrates the feature by spawning a remote /bin/bash process, attaching to it, and forwarding terminal resize events.
  • Supporting Changes:
    • The openapi.yaml specification and the generated oapi client have been updated to include the new API endpoints and request parameters.
    • New Go module dependencies (creack/pty, golang.org/x/term) were added to support PTY management.
    • The wrapper.sh scripts in the container images now ensure a valid HOSTNAME is always set.

Written by Cursor Bugbot for commit 55adbad. This will update automatically on new commits. Configure here.

Description generated by Mesa. Update settings

Copy link

@mesa-dot-dev mesa-dot-dev bot left a comment

Choose a reason for hiding this comment

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

Performed full review of 1d2d45e...7d69152

Analysis

  1. Goroutine and Connection Leaks: The HandleProcessAttach function creates multiple goroutines for I/O copying without proper cleanup mechanisms. There's no context-based cancellation, connection timeouts, or tracking to prevent resource exhaustion when clients disconnect improperly.

  2. PTY Process Cleanup Issues: If pty.Start(cmd) fails, there's no guaranteed cleanup of potentially started processes, which could lead to zombie process leaks.

  3. Security Vulnerabilities: The /attach endpoint lacks proper authentication beyond process ID validation, has no permission validation for process attachment, and allows multiple clients to attach to the same PTY which could cause output duplication and potential DoS attacks.

  4. Client Timeout Problems: While the client implementation handles terminal modes and resize events properly, it has indefinite blocking for I/O operations without proper timeout handling.

Tip

Help

Slash Commands:

  • /review - Request a full code review
  • /review latest - Review only changes since the last review
  • /describe - Generate PR description. This will update the PR body or issue comment depending on your configuration
  • /help - Get help with Mesa commands and configuration options

9 files reviewed | 0 comments | Edit Agent SettingsRead Docs

Copy link
Contributor

@Sayan- Sayan- left a comment

Choose a reason for hiding this comment

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

overall lgtm! nothing blocking ^^

Comment on lines +121 to +125
// Raw attach endpoint (HTTP hijack) - not part of OpenAPI spec
r.Get("/process/{process_id}/attach", func(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "process_id")
apiService.HandleProcessAttach(w, r, id)
})
Copy link
Contributor

Choose a reason for hiding this comment

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

from my understanding these routes will keep using all the router's middlewares. does that match yours? specifically curious on the stz implications

Comment on lines 652 to 653
_, _ = io.Copy(processRW, clientConn)
shutdown()
Copy link
Contributor

Choose a reason for hiding this comment

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

nice how simple this one gets to be

Resolve conflicts in process.go (keep both PTY cleanup and scale-to-zero
re-enable logic) and regenerate oapi.go from merged openapi.yaml.
r.Get("/process/{process_id}/attach", func(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "process_id")
apiService.HandleProcessAttach(w, r, id)
})
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this route uses all the router's middlewares including scale-to-zero. The behavior is actually correct for attach:

  1. When an attach request comes in, the STZ middleware disables scale-to-zero
  2. The handler hijacks the connection and blocks on <-done until the session ends
  3. Since HandleProcessAttach stays alive for the entire attach session, scale-to-zero remains disabled
  4. When the session ends (client disconnects or process exits), the handler returns and the middleware's defer re-enables scale-to-zero

So the STZ integration works correctly - the machine won't scale to zero while there's an active interactive session.

- Use buf.Reader instead of raw conn after HTTP hijack to consume any
  buffered data that was read ahead before the hijack
- Add uint16 overflow validation for rows/cols in ProcessResize (returns
  400 if values > 65535)
- Add uint16 overflow validation for rows/cols in ProcessSpawn before
  starting the PTY process

Addresses cursor[bot] review comments about potential data loss after
hijack and silent integer overflow when converting to uint16.
@rgarcia rgarcia merged commit 046ef0b into main Dec 31, 2025
4 checks passed
@rgarcia rgarcia deleted the shell branch December 31, 2025 20:27
if errno == syscall.EAGAIN || errno == syscall.EWOULDBLOCK {
continue
}
}
Copy link

Choose a reason for hiding this comment

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

Incorrect error type assertion fails to handle errno

The type assertion rerr.(syscall.Errno) in copyPTYToConn will never succeed because os.File.Read() wraps errors in *os.PathError, not raw syscall.Errno. This causes the EAGAIN/EWOULDBLOCK continue logic at lines 746-748 to fail silently—instead of continuing the loop to retry, the function returns early on line 750. Using errors.Is(rerr, syscall.EIO) and similar would correctly unwrap and match these errors.

Fix in Cursor Fix in Web

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.

3 participants