[python 2.7][requests 2.18.4] Header memory leak?

While debugging some memory leaks in our webservers, I noticed that I had a lot of headers (or things that very much look like headers) in `gc.garbage`.
I did a simple script to try to investigate the issue and it seems that it comes from the `requests` lib.
Doing a simple `requests.get('http://www.google.com')` will lead to a list of headers not collected.

## Expected Result

When doing `requests.get('http://www.google.com')`, and then calling `gc.garbage`, I expect not to have a list of headers staying in memory.

## Actual Result

When doing a simple GET request, I have a bunch of headers not collectable.

## Reproduction Steps

```python

import requests
import gc
import operator

gc.set_debug(gc.DEBUG_LEAK)

def collect():
    gc.collect()
    modules = dict()
    objects = dict()
    for g in gc.garbage:
        key = type(g).__name__
        modules[key] = modules.get(key, 0) + 1
        if key not in objects:
            objects[key] = []
        objects[key].append(g)
    sorted_modules = sorted(modules.items(), key=operator.itemgetter(1))
    print 'Modules: ', sorted_modules
    print 'First 10 lists:', objects.get('list', [])[:10]


def make_requests():
    # The bigger the range, the bigger the final list
    for _ in range(0, 10):
        requests.get('http://www.google.com')


make_requests()
collect()
```
Here is the result from the 2 prints.
I just print the first 10 headers, but as you can see, there are 808 objects lists (all headers)
```
Modules:  [('FastDictCache', 1), ('deque', 1), ('Buffer', 1), ('InMemoryHistory', 1), ('Event', 3), ('dict', 6), ('PoolKey', 20), *('list', 808)*]
First 10 lists: [[[[[[[...], [...], 'connection'], [...], 'accept-encoding'], [...], 'accept'], [...], 'user-agent'], [[...], [[...], [[...], [[...], [...], 'user-agent'], 'accept'], 'accept-encoding'], 'connection'], None], [[[[[[...], [...], 'accept-encoding'], [...], 'accept'], [...], 'user-agent'], [...], None], [[...], [[...], [[...], [[...], [...], None], 'user-agent'], 'accept'], 'accept-encoding'], 'connection'], [[[[[[...], [...], 'accept'], [...], 'user-agent'], [...], None], [...], 'connection'], [[...], [[...], [[...], [[...], [...], 'connection'], None], 'user-agent'], 'accept'], 'accept-encoding'], [[[[[[...], [...], 'user-agent'], [...], None], [...], 'connection'], [...], 'accept-encoding'], [[...], [[...], [[...], [[...], [...], 'accept-encoding'], 'connection'], None], 'user-agent'], 'accept'], [[[[[[...], [...], None], [...], 'connection'], [...], 'accept-encoding'], [...], 'accept'], [[...], [[...], [[...], [[...], [...], 'accept'], 'accept-encoding'], 'connection'], None], 'user-agent'], [[...], [...], None], [[[[[[[[...], [...], 'cache-control'], [...], 'content-type'], [...], 'referrer-policy'], [...], 'location'], [...], 'content-length'], [...], 'date'], [[...], [[...], [[...], [[...], [[...], [[...], [...], 'date'], 'content-length'], 'location'], 'referrer-policy'], 'content-type'], 'cache-control'], None], [[[[[[[[...], [...], 'content-type'], [...], 'referrer-policy'], [...], 'location'], [...], 'content-length'], [...], 'date'], [...], None], [[...], [[...], [[...], [[...], [[...], [[...], [...], None], 'date'], 'content-length'], 'location'], 'referrer-policy'], 'content-type'], 'cache-control'], [[[[[[[[...], [...], 'referrer-policy'], [...], 'location'], [...], 'content-length'], [...], 'date'], [...], None], [...], 'cache-control'], [[...], [[...], [[...], [[...], [[...], [[...], [...], 'cache-control'], None], 'date'], 'content-length'], 'location'], 'referrer-policy'], 'content-type'], [[[[[[[[...], [...], 'location'], [...], 'content-length'], [...], 'date'], [...], None], [...], 'cache-control'], [...], 'content-type'], [[...], [[...], [[...], [[...], [[...], [[...], [...], 'content-type'], 'cache-control'], None], 'date'], 'content-length'], 'location'], 'referrer-policy']]
```

## System Information

    $ python -m requests.help

```
python -m requests.help
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.6"
  },
  "implementation": {
    "name": "CPython",
    "version": "2.7.14"
  },
  "platform": {
    "release": "16.7.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.18.4"
  },
  "system_ssl": {
    "version": "100020cf"
  },
  "urllib3": {
    "version": "1.22"
  },
  "using_pyopenssl": false
}
```




Using your script verbatim, I see:

```
Modules:  []                                                                                                                                                                                   
Traceback (most recent call last):                                                                                                                                                             
  File "leak.py", line 29, in <module>                                                                                                                                                
    collect()                                                                                                                                                                                  
  File "leak.py", line 19, in collect                                                                                                                                                 
    print('First 10 lists:', objects['list'][:10])                                                                                                                                             
KeyError: 'list' 
```

Interesting. I ran the above on Python 3 because I missed the header's "Python 2.7" tag.

This is very bizarre given that Python 3 doesn't seem to leak this memory, but Python 2.7 does. My first guess is something to do with httplib given that all else is the pretty much the same between 2.7 and 3.6 on my machine besides language/core libraries

I was actually looking at this too. I can reproduce with urllib3 but it's ~20% of the leaking that we see with Requests (Requests: 530, urllib3:130). It's either at urllib3 or lower but Requests may be making it worse by holding onto something we don't need to.

What about this from https://docs.python.org/3.6/library/gc.html (emphasis mine):

> To debug a leaking program call gc.set_debug(gc.DEBUG_LEAK). Notice that this includes gc.DEBUG_SAVEALL, **causing garbage-collected objects to be saved in gc.garbage for inspection**.

So inspecting `gc.garbage` here isn't necessarily indicative of a leak. If I run OP's example without `gc.set_debug(gc.DEBUG_LEAK)` I don't see anything indicating a leak.

@sigmavirus24  As a reminder I tested in python 2.7 not 3.6. I didn't test in python 3.x so maybe there are no problem in 3.x

@drpoggi As far as I understood how `gc.garbage` work from https://docs.python.org/2/library/gc.html , if you don't set the  debug flag (at least (```gc.DEBUG_SAVEALL
When set, all unreachable objects found will be appended to garbage rather than being freed. This can be useful for debugging a leaking program.
```), you won't have anything in the `gc.garbage`.
If I just set `DEBUG_SAVEALL` instead of `DEBUG_LEAK` I have the same issue. 
and from the doc 
```
gc.garbage
A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects). [...]
If DEBUG_SAVEALL is set, then all unreachable objects will be added to this list rather than freed.
```
That's why I think that everything returned by `gc.garbage `are leaked. 
But I might be wrong. The doc says `unreachable` not `leaked`. 
Also 
```
Notice that this includes gc.DEBUG_SAVEALL, causing garbage-collected objects to be saved in gc.garbage for inspection.
```
So my interpretation on how to use the debug flag could be wrong.

I guess a more correct way would be to use:
```
gc.DEBUG_UNCOLLECTABLE
Print information of uncollectable objects found (objects which are not reachable but cannot be freed by the collector). These objects will be added to the garbage list.
```
but if I just set this, I have nothing in gc.garbage.

So the documentation of gc might be misleading, when you set `gc.DEBUG_LEAK`, you get all the objects unreachable (that will be freed) and potentially the one  that leaked.
I couldn't find a correct article on the web to help me on this.

Do we have a `gc` expert somewhere that might help us on the correct way to investigate this?

To be honest, I would be very surprised to discover such a leak in the lib that no one would have notice, but as I couldn't explain my results, I took the liberty to ask you directly.

How do I solve the same problem

@LashengRamsey did you confirm that you're even seeing an actual leak from Requests? This issue is still inconclusive it seems. How did you confirm that? Can you give us your system information so we can fix the leak?

If you have numpy 1.15, you can easily check for leaks with this code:
```python
from numpy.testing import assert_no_gc_cycles
import requests

with assert_no_gc_cycles():
    requests.get('http://www.google.com/')
```

If I understand it correctly, it seems as if Python 2's OrderedDict in collections leaks:
```python
from numpy.testing import assert_no_gc_cycles
from collections import OrderedDict

with assert_no_gc_cycles():
    a = OrderedDict()
    del a
```
and thus everything that uses it. I guess somone need's to fix the backport of using weakref from Python 3 implmentation.  @rhettinger does this seem like a correct analysis ?


Confirmed (when backporting the fix the leak stops), also urllib3 needs to be upgraded to latest version (1.24) which drops support for python 2.6 (and thus removes a bad copy of ordered_dict in urllib3/packages/ordered_dict.py which also has the leak). 

Since the problem is in Python 2.7's `OrderedDict` implementation I'm not sure there's anything Requests can do here. Closing for now.