Crash when using requests + concurrent.futures.ProcessPoolExecutor

I am attempting to make an asynchronous request using `requests.get()` via `concurrent.futures.ProcessPoolExecutor` and then perform analysis with numpy in the same script, all running on macOS 10.13.6 with Python 3.6.5. However, attempting to do so results in an error being thrown and a crash.

This issue only arises when numpy is imported and `executor.submit(requests.get ...` is called. There is no issue if numpy is not imported, and there is no issue if a function other than one from requests is passed to `executor.submit()`.  The error only occurs when a process pool is used to execute a request while numpy is imported.

I am unsure why it is that attempting to execute `requests.get()` with the process pool is causing a crash. It seems that numpy is launching a thread when imported, which explains part of the error message. Other functions can be run without issue using the process pool, only requests causes it to crash.

This article provides some insight into the error being thrown, and the logic behind it. http://sealiesoftware.com/blog/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html


## Expected Result

I expect the request to execute in one of the processes managed by the process pool executor, with the response available through the returned future.

## Actual Result

An error is thrown. Specifically, the error is the following:
```
objc[56600]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.
objc[56600]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
```


## Reproduction Steps
**Must run on macOS 10.13 (High Sierra)**
```python
import requests
import numpy
import concurrent.futures

executor = concurrent.futures.ProcessPoolExecutor(max_workers=2)

future = executor.submit(requests.get, 'https://google.com')

print(future.result())

```

## System Information

    $ python -m requests.help

```
{
  "chardet": {
    "version": "3.0.4"
  },
  "cryptography": {
    "version": ""
  },
  "idna": {
    "version": "2.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.6.5"
  },
  "platform": {
    "release": "17.7.0",
    "system": "Darwin"
  },
  "pyOpenSSL": {
    "openssl_version": "",
    "version": null
  },
  "requests": {
    "version": "2.19.1"
  },
  "system_ssl": {
    "version": "100020ff"
  },
  "urllib3": {
    "version": "1.23"
  },
  "using_pyopenssl": false
}
```

`numpy.__version__` gives `1.15.0rc1`

Hi there,

That's an awfully odd error message. Are you using https://github.com/ross/requests-futures as well?

Yes, I was originally using requests-futures when I encountered this error. After poking around a bit, I found that using requests-futures was not necessary to reproduce the error message.

So I finally had time to read the blog you linked to.

Threads and multiprocessing on *nix systems (like OSX) tend to work as one would expect, including sharing resources. It's possible this is due to an issue with `numpy`'s thread and our use of one (or more) of the following:

- sockets
- the queue library (involved with threading and multiprocessing)
- the compiled ssl extension

It's unclear which is the actual cause and it's unclear which project is actually at fault here. I can't imagine how we could change at this point though

I've recently seen a similar issue.  In my case it was while running an ansible-playbook which included a filter (which I wrote) using requests to dynamically locate the appropriate Linux repositories to use based on the RHEL release version; e.g., 7.6.

There were multiple targeted systems being provisioned and it seems that as a consequence of that ansible-playbook forked separate threads to parallelize the processing.  During this the following occurred:

`objc[74357]: +[NSValue initialize] may have been in progress in another thread when fork() was called.`
`objc[74357]: +[NSValue initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
`

It wasn't obvious where the problem originated (ansible? requests? python?), but using canned data in place of calling requests succeeded.  Replacing the use of requests with httplib also worked implying the problem begins with requests, even if not actually a problem with requests but rather something requests brings out.

---
requests version: 2.22.0
System info:
> sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.6
BuildVersion:   18G95

> ansible-playbook --version
ansible-playbook 2.8.2
  config file = None
  configured module search path = [u'/Users/jshimkus/.ansible/plugins/modules', u'/opt/local/share/ansible/plugins/modules']
  ansible python module location = /opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/ansible
  executable location = /opt/local/bin/ansible-playbook
  python version = 2.7.16 (default, Apr  1 2019, 14:50:41) [GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.46.3)]


It seems that python 3.8 Introduces some[ changes to how multiprocessing works on Mac](https://bugs.python.org/issue33725) (now using spawn instead of fork), so it might be worth rerunning your playbook on 3.8 if that's an option for you?

Just tested on python 3.8, and with a slight modification, my snippet for reproducing this error no longer causes a failure. As such, it might be possible to close this issue thanks to the changes in Python 3.8.

This is also using a freshly installed numpy+requests from pip, as well as macOS 10.15.

Error message when rerunning original snippet on 3.8:
```
RuntimeError: 
        An attempt has been made to start a new process before the
        current process has finished its bootstrapping phase.

        This probably means that you are not using fork to start your
        child processes and you have forgotten to use the proper idiom
        in the main module:

            if __name__ == '__main__':
                freeze_support()
                ...

        The "freeze_support()" line can be omitted if the program
        is not going to be frozen to produce an executable.
```

Modifying my snippet by moving my functions inside of `if __name__ == '__main__':` as follows resolved the issue for me.
```python
import requests
import numpy
import concurrent.futures


if __name__ == "__main__":
    executor = concurrent.futures.ProcessPoolExecutor(max_workers=2)

    future = executor.submit(requests.get, 'https://google.com')

    print(future.result())
```

For future finders of this problem:
I have hit this bug while writing my own lookup extension that was required to use urllib (in order to perform mtls with a passphrase which isn't possible in the builtin url fetch methods).
I have further root caused this to a cpython bug that is essentially not-to-be-fixed:
https://github.com/python/cpython/issues/58037