{"action":"created","issue":{"url":"https://api.github.com/repos/gregjones/httpcache/issues/62","repository_url":"https://api.github.com/repos/gregjones/httpcache","labels_url":"https://api.github.com/repos/gregjones/httpcache/issues/62/labels{/name}","comments_url":"https://api.github.com/repos/gregjones/httpcache/issues/62/comments","events_url":"https://api.github.com/repos/gregjones/httpcache/issues/62/events","html_url":"https://github.com/gregjones/httpcache/issues/62","id":205176031,"number":62,"title":"Memory leak in setModReq","user":{"login":"Kegsay","id":7190048,"avatar_url":"https://avatars.githubusercontent.com/u/7190048?v=3","gravatar_id":"","url":"https://api.github.com/users/Kegsay","html_url":"https://github.com/Kegsay","followers_url":"https://api.github.com/users/Kegsay/followers","following_url":"https://api.github.com/users/Kegsay/following{/other_user}","gists_url":"https://api.github.com/users/Kegsay/gists{/gist_id}","starred_url":"https://api.github.com/users/Kegsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kegsay/subscriptions","organizations_url":"https://api.github.com/users/Kegsay/orgs","repos_url":"https://api.github.com/users/Kegsay/repos","events_url":"https://api.github.com/users/Kegsay/events{/privacy}","received_events_url":"https://api.github.com/users/Kegsay/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2017-02-03T14:45:46Z","updated_at":"2017-02-16T12:11:00Z","closed_at":"2017-02-11T09:20:55Z","body":"Version: `master/413781778738c08fdbb98e1dd65f5abffe8832d0`\r\n\r\nI noticed that my Go process was consuming more and more memory over time, even though I had an LRU cache set up capped on # bytes. I traced it down using pprof to this library. It appeared that it was holding onto `http.Request` objects created from [cloneRequest](https://github.com/gregjones/httpcache/blob/413781778738c08fdbb98e1dd65f5abffe8832d0/httpcache.go#L539). These requests are being stored in a map, and superficially it looks like the library was clearing them out correctly when the request was over (response read or error occurred), so I spun up gdb:\r\n\r\n```\r\n$ gdb -p 11322\r\n(gdb) break httpcache.go:165\r\nBreakpoint 1 at 0x76040c: file /..../vendor/src/github.com/gregjones/httpcache/httpcache.go, line 165.\r\n(gdb) continue\r\n\r\nContinuing.\r\n[Switching to Thread 0x7f6cd1ffb700 (LWP 11337)]\r\n\r\nBreakpoint 1, github.com/gregjones/httpcache.(*Transport).setModReq (t=0xc420164910, orig=0xc42001b770, mod=0xc42001b860)\r\n165\t\tif mod == nil {\r\n\r\n(gdb) print t.modReq\r\n$5 = map[*net/http.Request]*net/http.Request = {\r\n  [0xc4209de1e0] = 0xc42001af00,\r\n  [0xc4203240f0] = 0xc4203241e0,\r\n  [0xc4209de780] = 0xc4209de870,\r\n  [0xc4209de5a0] = 0xc4209de690,\r\n  [0xc42001b770] = 0xc42001b860, \r\n  [0xc4203250e0] = 0xc4203251d0,\r\n  [0xc42001bc20] = 0xc42001bd10,\r\n  [0xc420324f00] = 0xc420324ff0,\r\n  [0xc4203242d0] = 0xc4203243c0,\r\n  [0xc42001a690] = 0xc42001a780,\r\n  [0xc420325950] = 0xc420325a40}\r\n\r\n(gdb) step\r\n166\t\t\tdelete(t.modReq, orig)\r\n\r\n(gdb) print orig\r\n$6 = (struct net/http.Request *) 0xc420325a40\r\n```\r\n\r\nNotice the problem? `orig` is not a valid **key** in the `map`, it's a **value**. This happens because of [this line](https://github.com/gregjones/httpcache/blob/413781778738c08fdbb98e1dd65f5abffe8832d0/httpcache.go#L228) which is then being passed to `setModReq` [here](https://github.com/gregjones/httpcache/blob/413781778738c08fdbb98e1dd65f5abffe8832d0/httpcache.go#L232) and [here](https://github.com/gregjones/httpcache/blob/413781778738c08fdbb98e1dd65f5abffe8832d0/httpcache.go#L238) which are now referencing `req2`, NOT `req`.\r\n\r\nThis means that `t.setModReq(req, nil)` is completely broken and will never delete any `http.Requests`, leaking them forever.\r\n"},"comment":{"url":"https://api.github.com/repos/gregjones/httpcache/issues/comments/280314533","html_url":"https://github.com/gregjones/httpcache/issues/62#issuecomment-280314533","issue_url":"https://api.github.com/repos/gregjones/httpcache/issues/62","id":280314533,"user":{"login":"Kegsay","id":7190048,"avatar_url":"https://avatars.githubusercontent.com/u/7190048?v=3","gravatar_id":"","url":"https://api.github.com/users/Kegsay","html_url":"https://github.com/Kegsay","followers_url":"https://api.github.com/users/Kegsay/followers","following_url":"https://api.github.com/users/Kegsay/following{/other_user}","gists_url":"https://api.github.com/users/Kegsay/gists{/gist_id}","starred_url":"https://api.github.com/users/Kegsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kegsay/subscriptions","organizations_url":"https://api.github.com/users/Kegsay/orgs","repos_url":"https://api.github.com/users/Kegsay/repos","events_url":"https://api.github.com/users/Kegsay/events{/privacy}","received_events_url":"https://api.github.com/users/Kegsay/received_events","type":"User","site_admin":false},"created_at":"2017-02-16T12:11:00Z","updated_at":"2017-02-16T12:11:00Z","body":"I can confirm that the PR has fixed this issue for us. Thank you! ⭐️ "}}
{"actor":{"display_login":"Kegsay"}}