11package compute
22
33import (
4+ "context"
45 "errors"
56 "fmt"
67 "io"
@@ -85,6 +86,16 @@ func newComputePty() *cobra.Command {
8586 }
8687 defer term .Restore (fd , oldState ) //nolint:errcheck
8788
89+ // Restore terminal on signals that would otherwise leave it raw.
90+ sigCh := make (chan os.Signal , 1 )
91+ signal .Notify (sigCh , syscall .SIGINT , syscall .SIGTERM )
92+ go func () {
93+ <- sigCh
94+ term .Restore (fd , oldState ) //nolint:errcheck
95+ os .Exit (1 )
96+ }()
97+ defer signal .Stop (sigCh )
98+
8899 client := api .NewComputeClient ()
89100 stream := client .OpenPtySession (ctx )
90101 stream .RequestHeader ().Set ("Authorization" , "Bearer " + token )
@@ -105,40 +116,44 @@ func newComputePty() *cobra.Command {
105116 return fmt .Errorf ("send pty init: %w" , err )
106117 }
107118
108- // Handle SIGWINCH for terminal resize.
109- sigwinch := make ( chan os. Signal , 1 )
110- signal . Notify ( sigwinch , syscall . SIGWINCH )
111- defer signal . Stop ( sigwinch )
119+ ctx , cancel := context . WithCancel ( ctx )
120+ defer cancel ( )
121+
122+ sendCh := make ( chan * civ1. OpenPtySessionRequest , 1 )
112123
113124 go func () {
114- for range sigwinch {
115- w , h , err := term .GetSize (fd )
116- if err != nil {
117- continue
125+ for {
126+ select {
127+ case msg := <- sendCh :
128+ _ = stream .Send (msg )
129+ case <- ctx .Done ():
130+ _ = stream .CloseRequest ()
131+ return
118132 }
119- _ = stream .Send (& civ1.OpenPtySessionRequest {
120- Message : & civ1.OpenPtySessionRequest_WindowResize {
121- WindowResize : & civ1.WindowResize {
122- Rows : uint32 (h ),
123- Cols : uint32 (w ),
124- },
125- },
126- })
127133 }
128134 }()
129135
136+ // Watch for terminal resize events (no-op on Windows).
137+ stopResize := watchTerminalResize (ctx , fd , sendCh )
138+ defer stopResize ()
139+
130140 // Forward stdin to the stream.
131141 go func () {
132142 buf := make ([]byte , 4096 ) //nolint:mnd
133143 for {
134144 n , err := os .Stdin .Read (buf )
135145 if n > 0 {
136- _ = stream .Send (& civ1.OpenPtySessionRequest {
137- Message : & civ1.OpenPtySessionRequest_Stdin {Stdin : buf [:n ]},
138- })
146+ data := make ([]byte , n )
147+ copy (data , buf [:n ])
148+ select {
149+ case sendCh <- & civ1.OpenPtySessionRequest {
150+ Message : & civ1.OpenPtySessionRequest_Stdin {Stdin : data },
151+ }:
152+ case <- ctx .Done ():
153+ return
154+ }
139155 }
140156 if err != nil {
141- _ = stream .CloseRequest ()
142157 return
143158 }
144159 }
@@ -159,6 +174,7 @@ func newComputePty() *cobra.Command {
159174 case * civ1.OpenPtySessionResponse_ExitCode :
160175 fmt .Fprintf (os .Stderr , "\r \n [exit %d]\r \n " , m .ExitCode )
161176 if m .ExitCode != 0 {
177+ term .Restore (fd , oldState ) //nolint:errcheck
162178 os .Exit (int (m .ExitCode ))
163179 }
164180 return nil
0 commit comments