Compare commits

..

7 Commits

Author SHA1 Message Date
Dallin Romney
807d95dd3f Merge pull request #9568 from yumosx/fix-lsof
fix(resource-monitoring): fix lsof file descriptor leak
2026-01-31 15:33:39 -08:00
Dallin Romney
895632c0a5 fix: detect WSL remote for shell PATH resolution (#9934)
When Windows host connects to WSL remote, getEnvPathFromUserShell() was
returning undefined because it checked only process.platform === "win32".

Add remoteName parameter to getEnvPathFromUserShell() and use the
isWindowsHostWithWslRemote pattern (consistent with resolveCommandForPlatform)
to allow shell PATH detection for WSL remotes.

Fixes #9737

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 15:26:05 -08:00
shanevcantwell
939b44b39f fix: detect WSL remote for shell PATH resolution
When Windows host connects to WSL remote, getEnvPathFromUserShell() was
returning undefined because it checked only process.platform === "win32".

Add remoteName parameter to getEnvPathFromUserShell() and use the
isWindowsHostWithWslRemote pattern (consistent with resolveCommandForPlatform)
to allow shell PATH detection for WSL remotes.

Fixes #9737

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 18:51:11 -07:00
alanw
056622faa0 fix: simplify file descriptor count calculation 2026-01-19 01:46:26 +00:00
alanw
676e31d28e fix(ResourceMonitoringService): prevent negative file descriptor counts and remove test cases 2026-01-16 05:17:39 +00:00
alanw
df83e66d5c fix(ResourceMonitoringService): initialize fd check time and count on start 2026-01-16 04:20:46 +00:00
alanw
a99288f25a fix(resource-monitoring): prevent file descriptor count leak by adding caching 2026-01-16 03:27:48 +00:00
3 changed files with 42 additions and 16 deletions

View File

@@ -563,10 +563,15 @@ Org-level secrets can only be used for MCP by Background Agents (https://docs.co
// Set the initial PATH from process.env
env.PATH = process.env.PATH;
// For non-Windows platforms, try to get the PATH from user shell
if (process.platform !== "win32") {
// For non-Windows platforms or WSL remotes, try to get the PATH from user shell
const ideInfo = await this.extras?.ide?.getIdeInfo();
const isWindowsHostWithWslRemote =
process.platform === "win32" && ideInfo?.remoteName === "wsl";
if (process.platform !== "win32" || isWindowsHostWithWslRemote) {
try {
const shellEnvPath = await getEnvPathFromUserShell();
const shellEnvPath = await getEnvPathFromUserShell(
ideInfo?.remoteName,
);
if (shellEnvPath && shellEnvPath !== process.env.PATH) {
env.PATH = shellEnvPath;
}

View File

@@ -2,9 +2,12 @@ import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
export async function getEnvPathFromUserShell(): Promise<string | undefined> {
if (process.platform === "win32") {
console.warn(`${getEnvPathFromUserShell.name} not implemented for Windows`);
export async function getEnvPathFromUserShell(
remoteName?: string,
): Promise<string | undefined> {
const isWindowsHostWithWslRemote =
process.platform === "win32" && remoteName === "wsl";
if (process.platform === "win32" && !isWindowsHostWithWslRemote) {
return undefined;
}

View File

@@ -45,6 +45,9 @@ class ResourceMonitoringService {
private maxHistorySize = 300; // Keep 5 minutes at 1s intervals
private lastCpuUsage = process.cpuUsage();
private lastTimestamp = Date.now();
private lastFdCheckTime = Date.now();
private fdCheckIntervalMs = 5000; // Check file descriptors every 5 seconds
private cacheFileCount: number | null = null;
async initialize(): Promise<void> {
// Start monitoring if verbose mode is enabled
@@ -70,6 +73,12 @@ class ResourceMonitoringService {
this.lastCpuUsage = process.cpuUsage();
this.lastTimestamp = Date.now();
// Initialize file descriptor count on start
this.updateFileDescriptorCount().catch(() => {
// Ignore errors during initialization
});
this.lastFdCheckTime = Date.now();
this.monitoringInterval = setInterval(() => {
this.collectResourceUsage();
}, this.intervalMs);
@@ -127,16 +136,10 @@ class ResourceMonitoringService {
},
};
// Try to get file descriptor count (Unix only)
this.getFileDescriptorCount()
.then((count) => {
if (count !== null) {
usage.fileDescriptors = count;
}
})
.catch(() => {
// Ignore errors for file descriptor counting
});
// Use cached file descriptor count to avoid lsof command leak
if (this.cacheFileCount !== null) {
usage.fileDescriptors = this.cacheFileCount;
}
return usage;
}
@@ -215,6 +218,14 @@ class ResourceMonitoringService {
this.resourceHistory = this.resourceHistory.slice(-this.maxHistorySize);
}
// Periodically update file descriptor count to prevent lsof command leak
// Issue: https://github.com/continuedev/continue/issues/9422
const now = Date.now();
if (now - this.lastFdCheckTime >= this.fdCheckIntervalMs) {
this.updateFileDescriptorCount();
this.lastFdCheckTime = now;
}
// Check for potential issues and log warnings
this.checkResourceThresholds(usage);
} catch (error) {
@@ -251,6 +262,13 @@ class ResourceMonitoringService {
}
}
private async updateFileDescriptorCount(): Promise<void> {
const count = await this.getFileDescriptorCount();
if (count !== null) {
this.cacheFileCount = count;
}
}
private async getFileDescriptorCount(): Promise<number | null> {
if (process.platform === "win32") {
return null; // Not supported on Windows