We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Exception: raise OSError("handle is closed")
When I initialized sentry_sdk and used concurrent.futures.process.ProcessPoolExecutor, the exception will be raised after python exit.

```
from concurrent.futures.process import ProcessPoolExecutor

import sentry_sdk

sentry_sdk.init(dsn="")


def test():
    ...


if __name__ == "__main__":
    with ProcessPoolExecutor(max_workers=4) as worker:
        worker.submit(test)
```

The exception:
```
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/Users/tony.li/miniconda3/lib/python3.7/concurrent/futures/process.py", line 101, in _python_exit
    thread_wakeup.wakeup()
  File "/Users/tony.li/miniconda3/lib/python3.7/concurrent/futures/process.py", line 89, in wakeup
    self._writer.send_bytes(b"")
  File "/Users/tony.li/miniconda3/lib/python3.7/multiprocessing/connection.py", line 183, in send_bytes
    self._check_closed()
  File "/Users/tony.li/miniconda3/lib/python3.7/multiprocessing/connection.py", line 136, in _check_closed
    raise OSError("handle is closed")
OSError: handle is closed
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sentry_sdk/integrations/threading.py`
Content:
```
1 from __future__ import absolute_import
2 
3 import sys
4 
5 from threading import Thread
6 
7 from sentry_sdk import Hub
8 from sentry_sdk._compat import reraise
9 from sentry_sdk.utils import event_from_exception
10 from sentry_sdk.integrations import Integration
11 
12 from sentry_sdk._types import MYPY
13 
14 if MYPY:
15     from typing import Any
16 
17 
18 class ThreadingIntegration(Integration):
19     identifier = "threading"
20 
21     def __init__(self, propagate_hub=False):
22         self.propagate_hub = propagate_hub
23 
24     @staticmethod
25     def setup_once():
26         # type: () -> None
27         old_start = Thread.start
28 
29         def sentry_start(self, *a, **kw):
30             hub = Hub.current
31             integration = hub.get_integration(ThreadingIntegration)
32             if integration is not None:
33                 if not integration.propagate_hub:
34                     hub_ = None
35                 else:
36                     hub_ = Hub(hub)
37 
38                 self.run = _wrap_run(hub_, self.run)
39 
40             return old_start(self, *a, **kw)  # type: ignore
41 
42         Thread.start = sentry_start  # type: ignore
43 
44 
45 def _wrap_run(parent_hub, old_run):
46     def run(*a, **kw):
47         hub = parent_hub or Hub.current
48 
49         with hub:
50             try:
51                 return old_run(*a, **kw)
52             except Exception:
53                 reraise(*_capture_exception())
54 
55     return run
56 
57 
58 def _capture_exception():
59     hub = Hub.current
60     exc_info = sys.exc_info()
61 
62     if hub.get_integration(ThreadingIntegration) is not None:
63         # If an integration is there, a client has to be there.
64         client = hub.client  # type: Any
65 
66         event, hint = event_from_exception(
67             exc_info,
68             client_options=client.options,
69             mechanism={"type": "threading", "handled": False},
70         )
71         hub.capture_event(event, hint=hint)
72 
73     return exc_info
74
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sentry_sdk/integrations/threading.py b/sentry_sdk/integrations/threading.py
--- a/sentry_sdk/integrations/threading.py
+++ b/sentry_sdk/integrations/threading.py
@@ -1,15 +1,13 @@
 from __future__ import absolute_import
 
 import sys
-
-from threading import Thread
+from threading import Thread, current_thread
 
 from sentry_sdk import Hub
 from sentry_sdk._compat import reraise
-from sentry_sdk.utils import event_from_exception
-from sentry_sdk.integrations import Integration
-
 from sentry_sdk._types import MYPY
+from sentry_sdk.integrations import Integration
+from sentry_sdk.utils import event_from_exception
 
 if MYPY:
     from typing import Any
@@ -34,21 +32,26 @@
                     hub_ = None
                 else:
                     hub_ = Hub(hub)
-
-                self.run = _wrap_run(hub_, self.run)
+                # Patching instance methods in `start()` creates a reference cycle if
+                # done in a naive way. See
+                # https://github.com/getsentry/sentry-python/pull/434
+                #
+                # In threading module, using current_thread API will access current thread instance
+                # without holding it to avoid a reference cycle in an easier way.
+                self.run = _wrap_run(hub_, self.run.__func__)
 
             return old_start(self, *a, **kw)  # type: ignore
 
         Thread.start = sentry_start  # type: ignore
 
 
-def _wrap_run(parent_hub, old_run):
+def _wrap_run(parent_hub, old_run_func):
     def run(*a, **kw):
         hub = parent_hub or Hub.current
-
         with hub:
             try:
-                return old_run(*a, **kw)
+                self = current_thread()
+                return old_run_func(self, *a, **kw)
             except Exception:
                 reraise(*_capture_exception())

{"golden_diff": "diff --git a/sentry_sdk/integrations/threading.py b/sentry_sdk/integrations/threading.py\n--- a/sentry_sdk/integrations/threading.py\n+++ b/sentry_sdk/integrations/threading.py\n@@ -1,15 +1,13 @@\n from __future__ import absolute_import\n \n import sys\n-\n-from threading import Thread\n+from threading import Thread, current_thread\n \n from sentry_sdk import Hub\n from sentry_sdk._compat import reraise\n-from sentry_sdk.utils import event_from_exception\n-from sentry_sdk.integrations import Integration\n-\n from sentry_sdk._types import MYPY\n+from sentry_sdk.integrations import Integration\n+from sentry_sdk.utils import event_from_exception\n \n if MYPY:\n     from typing import Any\n@@ -34,21 +32,26 @@\n                     hub_ = None\n                 else:\n                     hub_ = Hub(hub)\n-\n-                self.run = _wrap_run(hub_, self.run)\n+                # Patching instance methods in `start()` creates a reference cycle if\n+                # done in a naive way. See\n+                # https://github.com/getsentry/sentry-python/pull/434\n+                #\n+                # In threading module, using current_thread API will access current thread instance\n+                # without holding it to avoid a reference cycle in an easier way.\n+                self.run = _wrap_run(hub_, self.run.__func__)\n \n             return old_start(self, *a, **kw)  # type: ignore\n \n         Thread.start = sentry_start  # type: ignore\n \n \n-def _wrap_run(parent_hub, old_run):\n+def _wrap_run(parent_hub, old_run_func):\n     def run(*a, **kw):\n         hub = parent_hub or Hub.current\n-\n         with hub:\n             try:\n-                return old_run(*a, **kw)\n+                self = current_thread()\n+                return old_run_func(self, *a, **kw)\n             except Exception:\n                 reraise(*_capture_exception())\n", "issue": "Exception: raise OSError(\"handle is closed\")\nWhen I initialized sentry_sdk and used concurrent.futures.process.ProcessPoolExecutor, the exception will be raised after python exit.\r\n\r\n```\r\nfrom concurrent.futures.process import ProcessPoolExecutor\r\n\r\nimport sentry_sdk\r\n\r\nsentry_sdk.init(dsn=\"\")\r\n\r\n\r\ndef test():\r\n    ...\r\n\r\n\r\nif __name__ == \"__main__\":\r\n    with ProcessPoolExecutor(max_workers=4) as worker:\r\n        worker.submit(test)\r\n```\r\n\r\nThe exception:\r\n```\r\nError in atexit._run_exitfuncs:\r\nTraceback (most recent call last):\r\n  File \"/Users/tony.li/miniconda3/lib/python3.7/concurrent/futures/process.py\", line 101, in _python_exit\r\n    thread_wakeup.wakeup()\r\n  File \"/Users/tony.li/miniconda3/lib/python3.7/concurrent/futures/process.py\", line 89, in wakeup\r\n    self._writer.send_bytes(b\"\")\r\n  File \"/Users/tony.li/miniconda3/lib/python3.7/multiprocessing/connection.py\", line 183, in send_bytes\r\n    self._check_closed()\r\n  File \"/Users/tony.li/miniconda3/lib/python3.7/multiprocessing/connection.py\", line 136, in _check_closed\r\n    raise OSError(\"handle is closed\")\r\nOSError: handle is closed\r\n```\n", "before_files": [{"content": "from __future__ import absolute_import\n\nimport sys\n\nfrom threading import Thread\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk.utils import event_from_exception\nfrom sentry_sdk.integrations import Integration\n\nfrom sentry_sdk._types import MYPY\n\nif MYPY:\n    from typing import Any\n\n\nclass ThreadingIntegration(Integration):\n    identifier = \"threading\"\n\n    def __init__(self, propagate_hub=False):\n        self.propagate_hub = propagate_hub\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        old_start = Thread.start\n\n        def sentry_start(self, *a, **kw):\n            hub = Hub.current\n            integration = hub.get_integration(ThreadingIntegration)\n            if integration is not None:\n                if not integration.propagate_hub:\n                    hub_ = None\n                else:\n                    hub_ = Hub(hub)\n\n                self.run = _wrap_run(hub_, self.run)\n\n            return old_start(self, *a, **kw)  # type: ignore\n\n        Thread.start = sentry_start  # type: ignore\n\n\ndef _wrap_run(parent_hub, old_run):\n    def run(*a, **kw):\n        hub = parent_hub or Hub.current\n\n        with hub:\n            try:\n                return old_run(*a, **kw)\n            except Exception:\n                reraise(*_capture_exception())\n\n    return run\n\n\ndef _capture_exception():\n    hub = Hub.current\n    exc_info = sys.exc_info()\n\n    if hub.get_integration(ThreadingIntegration) is not None:\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        event, hint = event_from_exception(\n            exc_info,\n            client_options=client.options,\n            mechanism={\"type\": \"threading\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n    return exc_info\n", "path": "sentry_sdk/integrations/threading.py"}], "after_files": [{"content": "from __future__ import absolute_import\n\nimport sys\nfrom threading import Thread, current_thread\n\nfrom sentry_sdk import Hub\nfrom sentry_sdk._compat import reraise\nfrom sentry_sdk._types import MYPY\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.utils import event_from_exception\n\nif MYPY:\n    from typing import Any\n\n\nclass ThreadingIntegration(Integration):\n    identifier = \"threading\"\n\n    def __init__(self, propagate_hub=False):\n        self.propagate_hub = propagate_hub\n\n    @staticmethod\n    def setup_once():\n        # type: () -> None\n        old_start = Thread.start\n\n        def sentry_start(self, *a, **kw):\n            hub = Hub.current\n            integration = hub.get_integration(ThreadingIntegration)\n            if integration is not None:\n                if not integration.propagate_hub:\n                    hub_ = None\n                else:\n                    hub_ = Hub(hub)\n                # Patching instance methods in `start()` creates a reference cycle if\n                # done in a naive way. See\n                # https://github.com/getsentry/sentry-python/pull/434\n                #\n                # In threading module, using current_thread API will access current thread instance\n                # without holding it to avoid a reference cycle in an easier way.\n                self.run = _wrap_run(hub_, self.run.__func__)\n\n            return old_start(self, *a, **kw)  # type: ignore\n\n        Thread.start = sentry_start  # type: ignore\n\n\ndef _wrap_run(parent_hub, old_run_func):\n    def run(*a, **kw):\n        hub = parent_hub or Hub.current\n        with hub:\n            try:\n                self = current_thread()\n                return old_run_func(self, *a, **kw)\n            except Exception:\n                reraise(*_capture_exception())\n\n    return run\n\n\ndef _capture_exception():\n    hub = Hub.current\n    exc_info = sys.exc_info()\n\n    if hub.get_integration(ThreadingIntegration) is not None:\n        # If an integration is there, a client has to be there.\n        client = hub.client  # type: Any\n\n        event, hint = event_from_exception(\n            exc_info,\n            client_options=client.options,\n            mechanism={\"type\": \"threading\", \"handled\": False},\n        )\n        hub.capture_event(event, hint=hint)\n\n    return exc_info\n", "path": "sentry_sdk/integrations/threading.py"}]}