From b30ae5c5f01c36f39b9c301e59d8ad9fb24f7c1b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 12 Feb 2010 23:59:55 -0800 Subject: http: fix memory leak exposed in concurrent servers First off, this memory leak DOES NOT affect Unicorn itself. Unicorn allocates the HttpParser once and always reuses it in every sequential request. This leak affects applications which repeatedly allocate a new HTTP parser. Thus this bug affects _all_ deployments of Rainbows! and Zbatery. These servers allocate a new parser for every client connection. I misread the Data_Make_Struct/Data_Wrap_Struct documentation and ended up passing NULL as the "free" argument instead of -1, causing the memory to never be freed. From README.EXT in the MRI source which I misread: > The free argument is the function to free the pointer > allocation. If this is -1, the pointer will be just freed. > The functions mark and free will be called from garbage > collector. --- test/unit/test_http_parser.rb | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/unit/test_http_parser.rb b/test/unit/test_http_parser.rb index 0443b46..5b0ca9f 100644 --- a/test/unit/test_http_parser.rb +++ b/test/unit/test_http_parser.rb @@ -527,5 +527,21 @@ class HttpParserTest < Test::Unit::TestCase end end -end + # so we don't care about the portability of this test + # if it doesn't leak on Linux, it won't leak anywhere else + # unless your C compiler or platform is otherwise broken + LINUX_PROC_PID_STATUS = "/proc/self/status" + def test_memory_leak + match_rss = /^VmRSS:\s+(\d+)/ + if File.read(LINUX_PROC_PID_STATUS) =~ match_rss + before = $1.to_i + 1000000.times { Unicorn::HttpParser.new } + File.read(LINUX_PROC_PID_STATUS) =~ match_rss + after = $1.to_i + diff = after - before + assert(diff < 10000, "memory grew more than 10M: #{diff}") + end + end if RUBY_PLATFORM =~ /linux/ && test(?r, LINUX_PROC_PID_STATUS) + +end -- cgit v1.2.3-24-ge0c7