Offload functions to worker threads with shared memory primitives for Node.js.
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

test: fd dup diagnostic for NixOS CI debugging

+93
+4
.tangled/workflows/ci.yaml
··· 22 22 command: | 23 23 pnpm tsc --noEmit 24 24 25 + - name: fd-dup-diagnostic 26 + command: | 27 + node --test test/serve/fd-dup-diag.test.ts 28 + 25 29 - name: test 26 30 command: | 27 31 pnpm test
+89
test/serve/fd-dup-diag.test.ts
··· 1 + import { describe, it } from 'node:test'; 2 + import assert from 'node:assert/strict'; 3 + import { once } from 'node:events'; 4 + import { openSync, closeSync, existsSync, statSync } from 'node:fs'; 5 + import { platform } from 'node:process'; 6 + import { createServer, connect } from 'node:net'; 7 + 8 + describe('fd dup diagnostics', () => { 9 + it('reports platform and /proc/self/fd availability', () => { 10 + console.log('platform:', platform); 11 + console.log('/dev/fd exists:', existsSync('/dev/fd')); 12 + console.log('/proc/self/fd exists:', existsSync('/proc/self/fd')); 13 + if (existsSync('/proc/self/fd')) { 14 + try { 15 + const stat = statSync('/proc/self/fd'); 16 + console.log('/proc/self/fd stat:', stat.isDirectory() ? 'directory' : 'not-directory'); 17 + } catch (e: any) { 18 + console.log('/proc/self/fd stat error:', e.message); 19 + } 20 + } 21 + }); 22 + 23 + it('dup via /proc/self/fd works on a real socket', { timeout: 5000 }, async () => { 24 + const server = createServer(); 25 + server.listen(0); 26 + await once(server, 'listening'); 27 + const port = (server.address() as any).port; 28 + 29 + const client = connect(port); 30 + const [socket] = (await once(server, 'connection')) as [any]; 31 + 32 + const origFd: number = socket._handle.fd; 33 + console.log('origFd:', origFd); 34 + 35 + const path = platform === 'linux' ? `/proc/self/fd/${origFd}` : `/dev/fd/${origFd}`; 36 + console.log('dup path:', path); 37 + console.log('path exists:', existsSync(path)); 38 + 39 + let dupFd: number; 40 + try { 41 + dupFd = openSync(path, 'r+'); 42 + console.log('dup SUCCESS, dupFd:', dupFd); 43 + } catch (e: any) { 44 + console.log('dup FAILED:', e.message, e.code); 45 + socket.destroy(); 46 + client.destroy(); 47 + server.close(); 48 + assert.fail(`openSync('${path}', 'r+') failed: ${e.message}`); 49 + return; 50 + } 51 + 52 + // Verify the dup'd fd works: destroy original socket (closes origFd), 53 + // then write on the dup'd fd via a new Socket 54 + socket.destroy(); 55 + 56 + const dupSocket = new (await import('node:net')).Socket({ fd: dupFd, readable: true, writable: true }); 57 + dupSocket.write('hello from dup\n'); 58 + dupSocket.end(); 59 + 60 + const chunks: Buffer[] = []; 61 + client.on('data', (c: any) => chunks.push(Buffer.isBuffer(c) ? c : Buffer.from(c))); 62 + await once(client, 'end'); 63 + 64 + const result = Buffer.concat(chunks).toString('utf8'); 65 + console.log('client received:', JSON.stringify(result)); 66 + assert.equal(result, 'hello from dup\n'); 67 + 68 + server.close(); 69 + }); 70 + 71 + it('alternative: dup via process.binding if /proc/self/fd fails', { timeout: 5000 }, async () => { 72 + // Test whether we can use a different dup mechanism 73 + try { 74 + const binding = (process as any).binding('spawn_sync'); 75 + console.log('spawn_sync binding available:', !!binding); 76 + } catch (e: any) { 77 + console.log('spawn_sync binding not available:', e.message); 78 + } 79 + 80 + // Check if native addon-free dup is possible via other means 81 + try { 82 + const { execSync } = await import('node:child_process'); 83 + const result = execSync('ls /proc/self/fd/ 2>&1 || echo "NO_PROC"', { encoding: 'utf8' }); 84 + console.log('/proc/self/fd listing:', result.trim().slice(0, 200)); 85 + } catch (e: any) { 86 + console.log('ls /proc/self/fd failed:', e.message); 87 + } 88 + }); 89 + });