@@ -20,15 +20,6 @@ export interface NetworkInfo {
2020using_coder_connect :boolean ;
2121}
2222
23- /**
24- * Process information from find-process.
25- */
26- interface ProcessInfo {
27- pid :number ;
28- name :string ;
29- cmd :string ;
30- }
31-
3223/**
3324 * Options for creating an SshProcessMonitor.
3425 */
@@ -44,27 +35,6 @@ export interface SshProcessMonitorOptions {
4435remoteSshExtensionId :string ;
4536}
4637
47- /**
48- * Checks if a process is an actual SSH process (not a shell wrapper).
49- * Filters out processes like "sh -c ... | ssh ..." where ssh appears mid-command.
50- */
51- function isActualSshProcess ( p :ProcessInfo ) :boolean {
52- // Process name is exactly "ssh" or "ssh.exe"
53- if ( p . name === "ssh" || p . name === "ssh.exe" ) {
54- return true ;
55- }
56- // Command starts with ssh binary (not piped through shell)
57- if ( / ^ ( s s h | s s h \. e x e ) \s / i. test ( p . cmd ) ) {
58- return true ;
59- }
60- // Command starts with full path to ssh (Unix or Windows)
61- // e.g., "/usr/bin/ssh " or "C:\Program Files\OpenSSH\ssh.exe "
62- if ( / ^ [ \w / \\ : . - ] + ( [ / \\ ] ) s s h ( \. e x e ) ? \s / i. test ( p . cmd ) ) {
63- return true ;
64- }
65- return false ;
66- }
67-
6838/**
6939 * Finds the Remote SSH extension's log file path.
7040 */
@@ -139,6 +109,7 @@ export class SshProcessMonitor implements vscode.Disposable {
139109private currentPid :number | undefined ;
140110private logFilePath :string | undefined ;
141111private pendingTimeout :NodeJS . Timeout | undefined ;
112+ private lastStaleSearchTime = 0 ;
142113
143114private constructor ( options :SshProcessMonitorOptions ) {
144115this . options = {
@@ -216,7 +187,7 @@ export class SshProcessMonitor implements vscode.Disposable {
216187while ( ! this . disposed ) {
217188attempt ++ ;
218189
219- if ( attempt % 5 === 0 ) {
190+ if ( attempt % 10 === 0 ) {
220191logger . debug (
221192`SSH process search attempt${ attempt } for host:${ sshHost } ` ,
222193) ;
@@ -231,15 +202,6 @@ export class SshProcessMonitor implements vscode.Disposable {
231202return ;
232203}
233204
234- // Fall back to hostname-based search
235- // const pidByHost = await this.findSshProcessByHost();
236- // if (pidByHost !== undefined) {
237- // logger.info(`Found SSH process by hostname (PID: ${pidByHost})`);
238- // this.setCurrentPid(pidByHost);
239- // this.startMonitoring();
240- // return;
241- // }
242-
243205await this . delay ( pollInterval ) ;
244206}
245207}
@@ -262,6 +224,7 @@ export class SshProcessMonitor implements vscode.Disposable {
262224
263225const logContent = await fs . readFile ( logPath , "utf8" ) ;
264226this . options . logger . debug ( `Read Remote SSH log file:${ logPath } ` ) ;
227+
265228const port = findPort ( logContent ) ;
266229if ( ! port ) {
267230return undefined ;
@@ -280,45 +243,6 @@ export class SshProcessMonitor implements vscode.Disposable {
280243}
281244}
282245
283- /**
284- * Attempts to find an SSH process by hostname.
285- * Less accurate than port-based as multiple windows may connect to same host.
286- * Returns the PID if found, undefined otherwise.
287- */
288- private async findSshProcessByHost ( ) :Promise < number | undefined > {
289- const { sshHost, logger} = this . options ;
290-
291- try {
292- // Find all processes with "ssh" in name
293- const processes = await find ( "name" , "ssh" ) ;
294- const matches = processes . filter (
295- ( p ) => p . cmd . includes ( sshHost ) && isActualSshProcess ( p ) ,
296- ) ;
297-
298- if ( matches . length === 0 ) {
299- return undefined ;
300- }
301-
302- const preferred = matches . find (
303- ( p ) => p . name === "ssh" || p . name === "ssh.exe" ,
304- ) ;
305- if ( preferred ) {
306- return preferred . pid ;
307- }
308-
309- if ( matches . length > 1 ) {
310- logger . warn (
311- `Found${ matches . length } SSH processes for host, using first` ,
312- ) ;
313- }
314-
315- return matches [ 0 ] . pid ;
316- } catch ( error ) {
317- logger . debug ( `Error searching for SSH process:${ error } ` ) ;
318- return undefined ;
319- }
320- }
321-
322246/**
323247 * Updates the current PID and fires change events.
324248 */
@@ -406,15 +330,20 @@ export class SshProcessMonitor implements vscode.Disposable {
406330const ageMs = Date . now ( ) - stats . mtime . getTime ( ) ;
407331
408332if ( ageMs > staleThreshold ) {
409- logger . info (
333+ // Prevent tight loop: if we just searched due to stale, wait before searching again
334+ const timeSinceLastSearch = Date . now ( ) - this . lastStaleSearchTime ;
335+ if ( timeSinceLastSearch < staleThreshold ) {
336+ await this . delay ( staleThreshold - timeSinceLastSearch ) ;
337+ continue ;
338+ }
339+
340+ logger . debug (
410341`Network info stale (${ Math . round ( ageMs / 1000 ) } s old), searching for new SSH process` ,
411342) ;
412- this . currentPid = undefined ;
413- this . statusBarItem . hide ( ) ;
414- this . _onPidChange . fire ( undefined ) ;
415- this . searchForProcess ( ) . catch ( ( err ) => {
416- logger . error ( "Error restarting SSH process search" , err ) ;
417- } ) ;
343+
344+ // searchForProcess will update PID if a different process is found
345+ this . lastStaleSearchTime = Date . now ( ) ;
346+ await this . searchForProcess ( ) ;
418347return ;
419348}
420349