### Version v18.16.1 ### Platform Darwin Kernel Version 19.6.0 ### Subsystem none ### What steps will reproduce the bug? I can reliably reproduce a `Segmentation fault` by using the core `http2` module. ### Step 1: Acquire a TLS/SSL public+private key pair I followed [this guide](https://nodejs.org/api/tls.html#tlsssl-concepts) in the Node.js documentation to create a self-signed certificate. ### Step 2: Run this script to start an HTTP/2 server: ```js 'use strict'; const fs = require('fs'); const http2 = require('http2'); (async function main() { const sockets = new Set(); const sessions = new Set(); const server = http2.createSecureServer({ cert: fs.readFileSync('test-cert.pem'), key: fs.readFileSync('test-key.pem'), }); server.on('request', (req, res) => { const message = 'hello world.'; res.setHeader('Content-Length', String(Buffer.byteLength(message))); res.setHeader('Content-Type', 'text/plain; charset=utf-8'); res.writeHead(200); res.end(message); }); server.on('connection', (socket) => { sockets.add(socket); socket.on('close', () => sockets.delete(socket)); socket.setTimeout(2000, () => { console.log('socket timeout'); socket.resetAndDestroy(); }); }); server.on('session', (session) => { sessions.add(session); session.on('close', () => sessions.delete(session)); }); async function gracefullyClose() { for (const session of sessions) { session.close(); } await new Promise(resolve => server.close(resolve)); } await new Promise(resolve => server.listen(443, resolve)); console.log('Listening at https://localhost:443'); process.once('SIGINT', () => { console.log('closing...'); gracefullyClose().then(() => console.log('done')); }); })(); ``` ### Step 3: Open up Google Chrome (or probably any browser or HTTP client) and open the URL: `https://localhost:443`. You should get a `hello world.` plain text response. The only purpose of this step is to open an HTTP/2 session on the server. You don't really need Google Chrome specifically. ### Step 4: Wait for the Node.js server to print `socket timeout` in the console. This means the there was no activity on the socket for 2 seconds and so the socket was destroyed. ### Step 5: Close the Node.js server by triggering a SIGINT (i.e., press `ctrl+c` in the console). This will initiate a graceful shutdown of the server, which involves calling `session.close()` on every open session. This will cause the program to crash and print `Segmentation fault: 11`. ### How often does it reproduce? Is there a required condition? I can reliably reproduce it 100% of the time. ### What is the expected behavior? Why is that the expected behavior? The expected behavior is for the `session.close()` to not cause a segfault. Additionally, when the socket times out and `socket.resetAndDestroy()` is called, the session's `close` event should be emitted (which is currently not happening). The current behavior contradicts [the Node.js docs](https://nodejs.org/api/http2.html#http2session-and-sockets): > When either the Socket or the Http2Session are destroyed, both will be destroyed. ### What do you see instead? `Segmentation fault: 11` ### Additional information I know some people might suggest that I call `setTimeout` on the session instead of the socket, and that I use `session.destroy()` instead of `socket.resetAndDestroy()`. However, that isn't really an acceptable solution, because I need to close ALL connections that are established, even if an HTTP/2 session hasn't yet been established on that connection.