| // Run this program with valgrind or efence with --expose_gc to expose the |
| // problem. |
| |
| // Flags: --expose_gc |
| |
| var common = require('../common'); |
| var assert = require('assert'); |
| var HTTPParser = process.binding('http_parser').HTTPParser; |
| |
| var headersComplete = 0; |
| var messagesComplete = 0; |
| |
| function flushPool() { |
| new Buffer(Buffer.poolSize - 1); |
| gc(); |
| } |
| |
| function demoBug(part1, part2) { |
| flushPool(); |
| |
| var parser = new HTTPParser('REQUEST'); |
| |
| parser.headers = []; |
| parser.url = ''; |
| |
| parser.onHeaders = function(headers, url) { |
| parser.headers = parser.headers.concat(headers); |
| parser.url += url; |
| }; |
| |
| parser.onHeadersComplete = function(info) { |
| headersComplete++; |
| console.log('url', info.url); |
| }; |
| |
| parser.onBody = function(b, start, len) { }; |
| |
| parser.onMessageComplete = function() { |
| messagesComplete++; |
| }; |
| |
| |
| // We use a function to eliminate references to the Buffer b |
| // We want b to be GCed. The parser will hold a bad reference to it. |
| (function() { |
| var b = Buffer(part1); |
| flushPool(); |
| |
| console.log('parse the first part of the message'); |
| parser.execute(b, 0, b.length); |
| })(); |
| |
| flushPool(); |
| |
| (function() { |
| var b = Buffer(part2); |
| |
| console.log('parse the second part of the message'); |
| parser.execute(b, 0, b.length); |
| parser.finish(); |
| })(); |
| |
| flushPool(); |
| } |
| |
| |
| demoBug('POST /1', '/22 HTTP/1.1\r\n' + |
| 'Content-Type: text/plain\r\n' + |
| 'Content-Length: 4\r\n\r\n' + |
| 'pong'); |
| |
| demoBug('POST /1/22 HTTP/1.1\r\n' + |
| 'Content-Type: tex', 't/plain\r\n' + |
| 'Content-Length: 4\r\n\r\n' + |
| 'pong'); |
| |
| process.on('exit', function() { |
| assert.equal(2, headersComplete); |
| assert.equal(2, messagesComplete); |
| console.log('done!'); |
| }); |