broader support for SetDoNotAllowColumnSet + tests

This commit is contained in:
Peter Steinberger 2025-06-20 16:01:38 +02:00
parent eee508c36d
commit 08bdc5ecb4
8 changed files with 82 additions and 25 deletions

View file

@ -288,6 +288,9 @@ func startServer(cfg *config.Config, manager *session.Manager) error {
return fmt.Errorf("invalid port: %w", err)
}
// Set the resize flag on the manager
manager.SetDoNotAllowColumnSet(doNotAllowColumnSet)
// Create and configure server
server := api.NewServer(manager, staticPath, serverPassword, portInt)
server.SetNoSpawn(noSpawn)

View file

@ -162,7 +162,7 @@ func TestEscapeParser_Flush(t *testing.T) {
parser := NewEscapeParser()
// Process data with incomplete sequence
input := []byte("text\x1b[31") // incomplete CSI sequence
input := []byte("text\x1b[31") // incomplete CSI sequence
processed, _ := parser.ProcessData(input)
if !bytes.Equal(processed, []byte("text")) {

View file

@ -21,7 +21,7 @@ func TestProcessTerminatorIntegration(t *testing.T) {
}
terminator := NewProcessTerminator(session)
// Verify it was created with correct timeouts
if terminator.gracefulTimeout != 3*time.Second {
t.Errorf("Expected 3s graceful timeout, got %v", terminator.gracefulTimeout)
@ -34,16 +34,16 @@ func TestProcessTerminatorIntegration(t *testing.T) {
func TestCustomErrorsIntegration(t *testing.T) {
// Test custom error types
err := NewSessionError("test error", ErrSessionNotFound, "test-id")
if err.Code != ErrSessionNotFound {
t.Errorf("Expected code %v, got %v", ErrSessionNotFound, err.Code)
}
if !IsSessionError(err, ErrSessionNotFound) {
t.Error("IsSessionError should return true")
}
if GetSessionID(err) != "test-id" {
t.Errorf("Expected session ID 'test-id', got '%s'", GetSessionID(err))
}
}
}

View file

@ -14,9 +14,10 @@ import (
)
type Manager struct {
controlPath string
runningSessions map[string]*Session
mutex sync.RWMutex
controlPath string
runningSessions map[string]*Session
mutex sync.RWMutex
doNotAllowColumnSet bool
}
func NewManager(controlPath string) *Manager {
@ -26,12 +27,26 @@ func NewManager(controlPath string) *Manager {
}
}
// SetDoNotAllowColumnSet sets the flag to disable terminal resizing for all sessions
func (m *Manager) SetDoNotAllowColumnSet(value bool) {
m.mutex.Lock()
defer m.mutex.Unlock()
m.doNotAllowColumnSet = value
}
// GetDoNotAllowColumnSet returns the current value of the resize disable flag
func (m *Manager) GetDoNotAllowColumnSet() bool {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.doNotAllowColumnSet
}
func (m *Manager) CreateSession(config Config) (*Session, error) {
if err := os.MkdirAll(m.controlPath, 0755); err != nil {
return nil, fmt.Errorf("failed to create control directory: %w", err)
}
session, err := newSession(m.controlPath, config)
session, err := newSession(m.controlPath, config, m)
if err != nil {
return nil, err
}
@ -56,7 +71,7 @@ func (m *Manager) CreateSessionWithID(id string, config Config) (*Session, error
return nil, fmt.Errorf("failed to create control directory: %w", err)
}
session, err := newSessionWithID(m.controlPath, id, config)
session, err := newSessionWithID(m.controlPath, id, config, m)
if err != nil {
return nil, err
}
@ -86,7 +101,7 @@ func (m *Manager) GetSession(id string) (*Session, error) {
m.mutex.RUnlock()
// Fall back to loading from disk (for sessions that might have been started before this manager instance)
return loadSession(m.controlPath, id)
return loadSession(m.controlPath, id, m)
}
func (m *Manager) FindSession(nameOrID string) (*Session, error) {
@ -119,7 +134,7 @@ func (m *Manager) ListSessions() ([]*Info, error) {
continue
}
session, err := loadSession(m.controlPath, entry.Name())
session, err := loadSession(m.controlPath, entry.Name(), m)
if err != nil {
// Log the error when we can't load a session
if os.Getenv("VIBETUNNEL_DEBUG") != "" {

View file

@ -257,6 +257,12 @@ func (p *PTY) Run() error {
// Handle SIGWINCH in a separate goroutine
go func() {
for range winchCh {
// Check if resizing is disabled globally
if p.session.manager != nil && p.session.manager.GetDoNotAllowColumnSet() {
debugLog("[DEBUG] PTY.Run: Received SIGWINCH but resizing is disabled by server configuration")
continue
}
// Get current terminal size if we're attached to a terminal
if term.IsTerminal(int(os.Stdin.Fd())) {
width, height, err := term.GetSize(int(os.Stdin.Fd()))
@ -434,6 +440,11 @@ func (p *PTY) Attach() error {
signal.Notify(ch, syscall.SIGWINCH)
go func() {
for range ch {
// Check if resizing is disabled globally
if p.session.manager != nil && p.session.manager.GetDoNotAllowColumnSet() {
debugLog("[DEBUG] PTY.Attach: Received SIGWINCH but resizing is disabled by server configuration")
continue
}
if err := p.updateSize(); err != nil {
log.Printf("[ERROR] PTY.Attach: Failed to update size: %v", err)
}
@ -441,8 +452,13 @@ func (p *PTY) Attach() error {
}()
defer signal.Stop(ch)
if err := p.updateSize(); err != nil {
log.Printf("[ERROR] PTY.Attach: Failed to update initial size: %v", err)
// Only update size initially if resizing is allowed
if p.session.manager == nil || !p.session.manager.GetDoNotAllowColumnSet() {
if err := p.updateSize(); err != nil {
log.Printf("[ERROR] PTY.Attach: Failed to update initial size: %v", err)
}
} else {
debugLog("[DEBUG] PTY.Attach: Skipping initial resize - resizing is disabled by server configuration")
}
errCh := make(chan error, 2)

View file

@ -67,14 +67,15 @@ type Session struct {
stdinPipe *os.File
stdinMutex sync.Mutex
mu sync.RWMutex
manager *Manager // Reference to manager for accessing global settings
}
func newSession(controlPath string, config Config) (*Session, error) {
func newSession(controlPath string, config Config, manager *Manager) (*Session, error) {
id := uuid.New().String()
return newSessionWithID(controlPath, id, config)
return newSessionWithID(controlPath, id, config, manager)
}
func newSessionWithID(controlPath string, id string, config Config) (*Session, error) {
func newSessionWithID(controlPath string, id string, config Config, manager *Manager) (*Session, error) {
sessionPath := filepath.Join(controlPath, id)
// Only log in debug mode
@ -159,10 +160,11 @@ func newSessionWithID(controlPath string, id string, config Config) (*Session, e
ID: id,
controlPath: controlPath,
info: info,
manager: manager,
}, nil
}
func loadSession(controlPath, id string) (*Session, error) {
func loadSession(controlPath, id string, manager *Manager) (*Session, error) {
sessionPath := filepath.Join(controlPath, id)
info, err := LoadInfo(sessionPath)
if err != nil {
@ -173,6 +175,7 @@ func loadSession(controlPath, id string) (*Session, error) {
ID: id,
controlPath: controlPath,
info: info,
manager: manager,
}
// Validate that essential session files exist
@ -437,8 +440,9 @@ func (s *Session) cleanup() {
}
func (s *Session) Resize(width, height int) error {
if s.pty == nil {
return NewSessionError("session not started", ErrSessionNotRunning, s.ID)
// Check if resizing is disabled globally
if s.manager != nil && s.manager.GetDoNotAllowColumnSet() {
return NewSessionError("terminal resizing is disabled by server configuration", ErrInvalidInput, s.ID)
}
// Check if session is still alive
@ -464,7 +468,20 @@ func (s *Session) Resize(width, height int) error {
log.Printf("[ERROR] Failed to save session info after resize: %v", err)
}
// Resize the PTY
// If this is a spawned session, send resize command through control FIFO
if s.IsSpawned() {
cmd := &ControlCommand{
Cmd: "resize",
Cols: width,
Rows: height,
}
return SendControlCommand(s.Path(), cmd)
}
// For non-spawned sessions, resize the PTY directly
if s.pty == nil {
return NewSessionError("session not started", ErrSessionNotRunning, s.ID)
}
return s.pty.Resize(width, height)
}

View file

@ -14,6 +14,9 @@ func TestNewSession(t *testing.T) {
tmpDir := t.TempDir()
controlPath := filepath.Join(tmpDir, "control")
// Create a test manager
manager := NewManager(controlPath)
config := &Config{
Name: "test-session",
Cmdline: []string{"/bin/sh", "-c", "echo test"},
@ -22,7 +25,7 @@ func TestNewSession(t *testing.T) {
Height: 24,
}
session, err := newSession(controlPath, *config)
session, err := newSession(controlPath, *config, manager)
if err != nil {
t.Fatalf("newSession() error = %v", err)
}
@ -60,10 +63,13 @@ func TestNewSession_Defaults(t *testing.T) {
tmpDir := t.TempDir()
controlPath := filepath.Join(tmpDir, "control")
// Create a test manager
manager := NewManager(controlPath)
// Minimal config
config := &Config{}
session, err := newSession(controlPath, *config)
session, err := newSession(controlPath, *config, manager)
if err != nil {
t.Fatalf("newSession() error = %v", err)
}

View file

@ -73,4 +73,4 @@ func TestIsTerminal(t *testing.T) {
}
})
}
}
}