MCPcopy Index your code
hub / github.com/coder/coder / startNonPTYSession

Method startNonPTYSession

agent/agentssh/agentssh.go:654–711  ·  view source on GitHub ↗
(logger slog.Logger, session ssh.Session, magicTypeLabel string, cmd *exec.Cmd)

Source from the content-addressed store, hash-verified

652}
653
654func (s *Server) startNonPTYSession(logger slog.Logger, session ssh.Session, magicTypeLabel string, cmd *exec.Cmd) error {
655 s.metrics.sessionsTotal.WithLabelValues(magicTypeLabel, "no").Add(1)
656
657 // Create a process group and send SIGHUP to child processes,
658 // otherwise context cancellation will not propagate properly
659 // and SSH server close may be delayed.
660 cmd.SysProcAttr = cmdSysProcAttr()
661
662 // to match OpenSSH, we don't actually tear a non-TTY command down, even if the session ends. OpenSSH closes the
663 // pipes to the process when the session ends; which is what happens here since we wire the command up to the
664 // session for I/O.
665 // c.f. https://github.com/coder/coder/issues/18519#issuecomment-3019118271
666 cmd.Cancel = nil
667
668 cmd.Stdout = session
669 cmd.Stderr = session.Stderr()
670 // This blocks forever until stdin is received if we don't
671 // use StdinPipe. It's unknown what causes this.
672 stdinPipe, err := cmd.StdinPipe()
673 if err != nil {
674 s.metrics.sessionErrors.WithLabelValues(magicTypeLabel, "no", "stdin_pipe").Add(1)
675 return xerrors.Errorf("create stdin pipe: %w", err)
676 }
677 go func() {
678 _, err := io.Copy(stdinPipe, session)
679 if err != nil {
680 s.metrics.sessionErrors.WithLabelValues(magicTypeLabel, "no", "stdin_io_copy").Add(1)
681 }
682 _ = stdinPipe.Close()
683 }()
684 err = cmd.Start()
685 if err != nil {
686 s.metrics.sessionErrors.WithLabelValues(magicTypeLabel, "no", "start_command").Add(1)
687 return xerrors.Errorf("start: %w", err)
688 }
689
690 // Since we don't cancel the process when the session stops, we still need to tear it down if we are closing. So
691 // track it here.
692 if !s.trackProcess(cmd.Process, true) {
693 // must be closing
694 err = cmdCancel(logger, cmd.Process)
695 return xerrors.Errorf("failed to track process: %w", err)
696 }
697 defer s.trackProcess(cmd.Process, false)
698
699 sigs := make(chan ssh.Signal, 1)
700 session.Signals(sigs)
701 defer func() {
702 session.Signals(nil)
703 close(sigs)
704 }()
705 go func() {
706 for sig := range sigs {
707 handleSignal(logger, sig, cmd.Process, s.metrics, magicTypeLabel)
708 }
709 }()
710 return cmd.Wait()
711}

Callers 1

sessionStartMethod · 0.95

Calls 13

trackProcessMethod · 0.95
handleSignalFunction · 0.85
WithLabelValuesMethod · 0.80
StderrMethod · 0.80
cmdSysProcAttrFunction · 0.70
cmdCancelFunction · 0.70
AddMethod · 0.65
CopyMethod · 0.65
CloseMethod · 0.65
StartMethod · 0.65
SignalsMethod · 0.65
WaitMethod · 0.65

Tested by

no test coverage detected