Complex HTTP2/TLS socket state issue requiring deep protocol knowledge.
The issue involves an assertion failure in TLSWrap when handling zombie HTTP/2 sessions with closed sockets. Reproducing requires network manipulation and understanding of HTTP/2 session lifecycle. The main challenge is diagnosing the socket state propagation issue without breaking existing functionality.
v22.13.1
Darwin 24.3.0 (macOS, arm64)
http2, tls
We created a test that simulates a network "black hole" using macOS pf firewall.
Prerequisites: Generate self-signed certificates in the same directory:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/CN=localhost"
// test-zombie.js - Reproduces Node.js HTTP/2 assertion failure
// Run with: sudo node test-zombie.js
//
// This triggers: Assertion failed: is_write_in_progress()
// in node::http2::Http2Session::OnStreamAfterWrite
const http2 = require('http2')
const { spawn, execSync } = require('child_process')
const PORT = 8444
async function main() {
if (process.getuid() !== 0) {
console.log('Run with: sudo node test-zombie.js')
process.exit(1)
}
// Cleanup from previous runs
try {
execSync(`lsof -ti:${PORT} | xargs kill -9 2>/dev/null || true`)
execSync('pfctl -a zombie_test -F all 2>/dev/null || true')
} catch (e) {}
await new Promise(r => setTimeout(r, 500))
console.log('Node version:', process.version)
console.log('PID:', process.pid)
// Start server as child process
const server = spawn('node', ['-e', `
const http2 = require('http2')
const fs = require('fs')
const server = http2.createSecureServer({
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem'),
})
server.on('stream', (s, h) => {
s.respond({ ':status': 200 })
s.end('ok')
})
server.listen(${PORT}, () => console.log('Server ready'))
setInterval(() => {}, 10000)
`], { stdio: ['ignore', 'pipe', 'pipe'] })
server.stdout.on('data', d => console.log('[SERVER]', d.toString().trim()))
server.stderr.on('data', d => console.log('[SERV
Claim this issue to let others know you're working on it. You'll earn 10 points when you complete it!