Skip to content

Commit 99021ae

Browse files
committed
fix: add fallback for ss builds that reject sport filter
- Some ss builds don't support 'sport = :port' filter syntax - Detect filter failure (empty stdout, stderr mentions 'filter') - Fallback to unfiltered 'ss -tlnp' and parse full output - Use regex to match exact port with word boundary (e.g., :8888\b) - Extract pid=NUMBER from matching lines only - Prevents false positives (port 8888 won't match 88880) - Maintains Set<number> for automatic PID deduplication - Preserves throwOnStdErr: false throughout - Handles null/empty output safely
1 parent 6bff35b commit 99021ae

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

src/kernels/deepnote/deepnoteServerStarter.node.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -824,11 +824,43 @@ export class DeepnoteServerStarter implements IDeepnoteServerStarter, IExtension
824824
// Fallback to ss if lsof didn't find anything or failed
825825
if (uniquePids.size === 0) {
826826
try {
827+
// Try ss with filter first
827828
const ssResult = await processService.exec('ss', ['-tlnp', `sport = :${port}`], {
828829
throwOnStdErr: false
829830
});
830-
if (ssResult.stdout) {
831-
// Parse ss output: look for pid=<number>
831+
832+
// Check if filtered call succeeded (some ss builds reject the filter)
833+
const filterFailed =
834+
!ssResult.stdout ||
835+
ssResult.stdout.trim().length === 0 ||
836+
(ssResult.stderr && ssResult.stderr.includes('filter'));
837+
838+
if (filterFailed) {
839+
logger.debug(`ss filter not supported, trying without filter...`);
840+
// Run ss without filter and parse full output
841+
const ssUnfilteredResult = await processService.exec('ss', ['-tlnp'], {
842+
throwOnStdErr: false
843+
});
844+
845+
if (ssUnfilteredResult.stdout) {
846+
const lines = ssUnfilteredResult.stdout.split('\n');
847+
for (const line of lines) {
848+
// Match lines containing the port (e.g., ":8888" or ":8888 ")
849+
const portPattern = new RegExp(`:${port}\\b`);
850+
if (portPattern.test(line)) {
851+
// Extract pid=<number> from matching lines
852+
const pidMatches = line.matchAll(/pid=(\d+)/g);
853+
for (const match of pidMatches) {
854+
const pid = parseInt(match[1], 10);
855+
if (!isNaN(pid) && pid > 0) {
856+
uniquePids.add(pid);
857+
}
858+
}
859+
}
860+
}
861+
}
862+
} else if (ssResult.stdout) {
863+
// Filtered call succeeded, parse its output
832864
const pidMatches = ssResult.stdout.matchAll(/pid=(\d+)/g);
833865
for (const match of pidMatches) {
834866
const pid = parseInt(match[1], 10);

0 commit comments

Comments
 (0)