prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  RQ: Job shutdown problems
  RQ forks, so each job will have its own transport. This is not a great situation as we would have to block each job to send out pending events.
  
  Right now this can mean that some events of a job go missing.
  
  Idea would be to use `multiprocessing.Queue` inside of the transport, but unclear if we can pull that off without disrupting other usecases.
  
  </issue>
  <code>
  [start of setup.py]
  1 #!/usr/bin/env python
  2 
  3 """
  4 Sentry-Python - Sentry SDK for Python
  5 =====================================
  6 
  7 **Sentry-Python is an SDK for Sentry.** Check out `GitHub
  8 <https://github.com/getsentry/sentry-python>`_ to find out more.
  9 """
  10 
  11 from setuptools import setup, find_packages
  12 
  13 setup(
  14     name="sentry-sdk",
  15     version="0.5.1",
  16     author="Sentry Team and Contributors",
  17     author_email="hello@getsentry.com",
  18     url="https://github.com/getsentry/sentry-python",
  19     description="Python client for Sentry (https://getsentry.com)",
  20     long_description=__doc__,
  21     packages=find_packages(exclude=("tests", "tests.*")),
  22     zip_safe=False,
  23     license="BSD",
  24     install_requires=["urllib3", "certifi"],
  25     extras_require={"flask": ["flask>=0.8", "blinker>=1.1"]},
  26     classifiers=[
  27         'Development Status :: 5 - Production/Stable',
  28         'Environment :: Web Environment',
  29         'Intended Audience :: Developers',
  30         'License :: OSI Approved :: BSD License',
  31         'Operating System :: OS Independent',
  32         'Programming Language :: Python',
  33         'Programming Language :: Python :: 2',
  34         'Programming Language :: Python :: 2.7',
  35         'Programming Language :: Python :: 3',
  36         'Programming Language :: Python :: 3.4',
  37         'Programming Language :: Python :: 3.5',
  38         'Programming Language :: Python :: 3.6',
  39         'Programming Language :: Python :: 3.7',
  40         'Topic :: Software Development :: Libraries :: Python Modules',
  41     ],
  42 )
  43
  [end of setup.py]
  [start of sentry_sdk/integrations/rq.py]
  1 from __future__ import absolute_import
  2 
  3 import weakref
  4 
  5 from sentry_sdk.hub import Hub
  6 from sentry_sdk.integrations import Integration
  7 from sentry_sdk.utils import capture_internal_exceptions, event_from_exception
  8 
  9 from rq.timeouts import JobTimeoutException
  10 from rq.worker import Worker
  11 
  12 
  13 class RqIntegration(Integration):
  14     identifier = "rq"
  15 
  16     @staticmethod
  17     def setup_once():
  18 
  19         old_perform_job = Worker.perform_job
  20 
  21         def sentry_patched_perform_job(self, job, *args, **kwargs):
  22             hub = Hub.current
  23             integration = hub.get_integration(RqIntegration)
  24 
  25             if integration is None:
  26                 return old_perform_job(self, job, *args, **kwargs)
  27 
  28             with hub.push_scope() as scope:
  29                 scope.add_event_processor(_make_event_processor(weakref.ref(job)))
  30                 return old_perform_job(self, job, *args, **kwargs)
  31 
  32         Worker.perform_job = sentry_patched_perform_job
  33 
  34         old_handle_exception = Worker.handle_exception
  35 
  36         def sentry_patched_handle_exception(self, job, *exc_info, **kwargs):
  37             _capture_exception(exc_info)
  38             return old_handle_exception(self, job, *exc_info, **kwargs)
  39 
  40         Worker.handle_exception = sentry_patched_handle_exception
  41 
  42 
  43 def _make_event_processor(weak_job):
  44     def event_processor(event, hint):
  45         job = weak_job()
  46         if job is not None:
  47             with capture_internal_exceptions():
  48                 if "transaction" not in event:
  49                     event["transaction"] = job.func_name
  50 
  51             with capture_internal_exceptions():
  52                 extra = event.setdefault("extra", {})
  53                 extra["rq-job"] = {
  54                     "job_id": job.id,
  55                     "func": job.func_name,
  56                     "args": job.args,
  57                     "kwargs": job.kwargs,
  58                     "description": job.description,
  59                 }
  60 
  61         if "exc_info" in hint:
  62             with capture_internal_exceptions():
  63                 if issubclass(hint["exc_info"][0], JobTimeoutException):
  64                     event["fingerprint"] = ["rq", "JobTimeoutException", job.func_name]
  65 
  66         return event
  67 
  68     return event_processor
  69 
  70 
  71 def _capture_exception(exc_info, **kwargs):
  72     hub = Hub.current
  73     if hub.get_integration(RqIntegration) is None:
  74         return
  75     event, hint = event_from_exception(
  76         exc_info,
  77         client_options=hub.client.options,
  78         mechanism={"type": "rq", "handled": False},
  79     )
  80 
  81     hub.capture_event(event, hint=hint)
  82
  [end of sentry_sdk/integrations/rq.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py
  --- a/sentry_sdk/integrations/rq.py
  +++ b/sentry_sdk/integrations/rq.py
  @@ -27,7 +27,18 @@
   
               with hub.push_scope() as scope:
                   scope.add_event_processor(_make_event_processor(weakref.ref(job)))
  -                return old_perform_job(self, job, *args, **kwargs)
  +                rv = old_perform_job(self, job, *args, **kwargs)
  +
  +            if self.is_horse:
  +                # We're inside of a forked process and RQ is
  +                # about to call `os._exit`. Make sure that our
  +                # events get sent out.
  +                #
  +                # Closing the client should not affect other jobs since
  +                # we're in a different process
  +                hub.client.close()
  +
  +            return rv
   
           Worker.perform_job = sentry_patched_perform_job
   
  diff --git a/setup.py b/setup.py
  --- a/setup.py
  +++ b/setup.py
  @@ -24,19 +24,19 @@
       install_requires=["urllib3", "certifi"],
       extras_require={"flask": ["flask>=0.8", "blinker>=1.1"]},
       classifiers=[
  -        'Development Status :: 5 - Production/Stable',
  -        'Environment :: Web Environment',
  -        'Intended Audience :: Developers',
  -        'License :: OSI Approved :: BSD License',
  -        'Operating System :: OS Independent',
  -        'Programming Language :: Python',
  -        'Programming Language :: Python :: 2',
  -        'Programming Language :: Python :: 2.7',
  -        'Programming Language :: Python :: 3',
  -        'Programming Language :: Python :: 3.4',
  -        'Programming Language :: Python :: 3.5',
  -        'Programming Language :: Python :: 3.6',
  -        'Programming Language :: Python :: 3.7',
  -        'Topic :: Software Development :: Libraries :: Python Modules',
  +        "Development Status :: 5 - Production/Stable",
  +        "Environment :: Web Environment",
  +        "Intended Audience :: Developers",
  +        "License :: OSI Approved :: BSD License",
  +        "Operating System :: OS Independent",
  +        "Programming Language :: Python",
  +        "Programming Language :: Python :: 2",
  +        "Programming Language :: Python :: 2.7",
  +        "Programming Language :: Python :: 3",
  +        "Programming Language :: Python :: 3.4",
  +        "Programming Language :: Python :: 3.5",
  +        "Programming Language :: Python :: 3.6",
  +        "Programming Language :: Python :: 3.7",
  +        "Topic :: Software Development :: Libraries :: Python Modules",
       ],
   )
  
verification_info: {"golden_diff": "diff --git a/sentry_sdk/integrations/rq.py b/sentry_sdk/integrations/rq.py\n--- a/sentry_sdk/integrations/rq.py\n+++ b/sentry_sdk/integrations/rq.py\n@@ -27,7 +27,18 @@\n \n             with hub.push_scope() as scope:\n                 scope.add_event_processor(_make_event_processor(weakref.ref(job)))\n-                return old_perform_job(self, job, *args, **kwargs)\n+                rv = old_perform_job(self, job, *args, **kwargs)\n+\n+            if self.is_horse:\n+                # We're inside of a forked process and RQ is\n+                # about to call `os._exit`. Make sure that our\n+                # events get sent out.\n+                #\n+                # Closing the client should not affect other jobs since\n+                # we're in a different process\n+                hub.client.close()\n+\n+            return rv\n \n         Worker.perform_job = sentry_patched_perform_job\n \ndiff --git a/setup.py b/setup.py\n--- a/setup.py\n+++ b/setup.py\n@@ -24,19 +24,19 @@\n     install_requires=[\"urllib3\", \"certifi\"],\n     extras_require={\"flask\": [\"flask>=0.8\", \"blinker>=1.1\"]},\n     classifiers=[\n-        'Development Status :: 5 - Production/Stable',\n-        'Environment :: Web Environment',\n-        'Intended Audience :: Developers',\n-        'License :: OSI Approved :: BSD License',\n-        'Operating System :: OS Independent',\n-        'Programming Language :: Python',\n-        'Programming Language :: Python :: 2',\n-        'Programming Language :: Python :: 2.7',\n-        'Programming Language :: Python :: 3',\n-        'Programming Language :: Python :: 3.4',\n-        'Programming Language :: Python :: 3.5',\n-        'Programming Language :: Python :: 3.6',\n-        'Programming Language :: Python :: 3.7',\n-        'Topic :: Software Development :: Libraries :: Python Modules',\n+        \"Development Status :: 5 - Production/Stable\",\n+        \"Environment :: Web Environment\",\n+        \"Intended Audience :: Developers\",\n+        \"License :: OSI Approved :: BSD License\",\n+        \"Operating System :: OS Independent\",\n+        \"Programming Language :: Python\",\n+        \"Programming Language :: Python :: 2\",\n+        \"Programming Language :: Python :: 2.7\",\n+        \"Programming Language :: Python :: 3\",\n+        \"Programming Language :: Python :: 3.4\",\n+        \"Programming Language :: Python :: 3.5\",\n+        \"Programming Language :: Python :: 3.6\",\n+        \"Programming Language :: Python :: 3.7\",\n+        \"Topic :: Software Development :: Libraries :: Python Modules\",\n     ],\n )\n", "issue": "RQ: Job shutdown problems\nRQ forks, so each job will have its own transport. This is not a great situation as we would have to block each job to send out pending events.\r\n\r\nRight now this can mean that some events of a job go missing.\r\n\r\nIdea would be to use `multiprocessing.Queue` inside of the transport, but unclear if we can pull that off without disrupting other usecases.\n", "before_files": [{"content": "#!/usr/bin/env python\n\n\"\"\"\nSentry-Python - Sentry SDK for Python\n=====================================\n\n**Sentry-Python is an SDK for Sentry.** Check out `GitHub\n<https://github.com/getsentry/sentry-python>`_ to find out more.\n\"\"\"\n\nfrom setuptools import setup, find_packages\n\nsetup(\n    name=\"sentry-sdk\",\n    version=\"0.5.1\",\n    author=\"Sentry Team and Contributors\",\n    author_email=\"hello@getsentry.com\",\n    url=\"https://github.com/getsentry/sentry-python\",\n    description=\"Python client for Sentry (https://getsentry.com)\",\n    long_description=__doc__,\n    packages=find_packages(exclude=(\"tests\", \"tests.*\")),\n    zip_safe=False,\n    license=\"BSD\",\n    install_requires=[\"urllib3\", \"certifi\"],\n    extras_require={\"flask\": [\"flask>=0.8\", \"blinker>=1.1\"]},\n    classifiers=[\n        'Development Status :: 5 - Production/Stable',\n        'Environment :: Web Environment',\n        'Intended Audience :: Developers',\n        'License :: OSI Approved :: BSD License',\n        'Operating System :: OS Independent',\n        'Programming Language :: Python',\n        'Programming Language :: Python :: 2',\n        'Programming Language :: Python :: 2.7',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.4',\n        'Programming Language :: Python :: 3.5',\n        'Programming Language :: Python :: 3.6',\n        'Programming Language :: Python :: 3.7',\n        'Topic :: Software Development :: Libraries :: Python Modules',\n    ],\n)\n", "path": "setup.py"}, {"content": "from __future__ import absolute_import\n\nimport weakref\n\nfrom sentry_sdk.hub import Hub\nfrom sentry_sdk.integrations import Integration\nfrom sentry_sdk.utils import capture_internal_exceptions, event_from_exception\n\nfrom rq.timeouts import JobTimeoutException\nfrom rq.worker import Worker\n\n\nclass RqIntegration(Integration):\n    identifier = \"rq\"\n\n    @staticmethod\n    def setup_once():\n\n        old_perform_job = Worker.perform_job\n\n        def sentry_patched_perform_job(self, job, *args, **kwargs):\n            hub = Hub.current\n            integration = hub.get_integration(RqIntegration)\n\n            if integration is None:\n                return old_perform_job(self, job, *args, **kwargs)\n\n            with hub.push_scope() as scope:\n                scope.add_event_processor(_make_event_processor(weakref.ref(job)))\n                return old_perform_job(self, job, *args, **kwargs)\n\n        Worker.perform_job = sentry_patched_perform_job\n\n        old_handle_exception = Worker.handle_exception\n\n        def sentry_patched_handle_exception(self, job, *exc_info, **kwargs):\n            _capture_exception(exc_info)\n            return old_handle_exception(self, job, *exc_info, **kwargs)\n\n        Worker.handle_exception = sentry_patched_handle_exception\n\n\ndef _make_event_processor(weak_job):\n    def event_processor(event, hint):\n        job = weak_job()\n        if job is not None:\n            with capture_internal_exceptions():\n                if \"transaction\" not in event:\n                    event[\"transaction\"] = job.func_name\n\n            with capture_internal_exceptions():\n                extra = event.setdefault(\"extra\", {})\n                extra[\"rq-job\"] = {\n                    \"job_id\": job.id,\n                    \"func\": job.func_name,\n                    \"args\": job.args,\n                    \"kwargs\": job.kwargs,\n                    \"description\": job.description,\n                }\n\n        if \"exc_info\" in hint:\n            with capture_internal_exceptions():\n                if issubclass(hint[\"exc_info\"][0], JobTimeoutException):\n                    event[\"fingerprint\"] = [\"rq\", \"JobTimeoutException\", job.func_name]\n\n        return event\n\n    return event_processor\n\n\ndef _capture_exception(exc_info, **kwargs):\n    hub = Hub.current\n    if hub.get_integration(RqIntegration) is None:\n        return\n    event, hint = event_from_exception(\n        exc_info,\n        client_options=hub.client.options,\n        mechanism={\"type\": \"rq\", \"handled\": False},\n    )\n\n    hub.capture_event(event, hint=hint)\n", "path": "sentry_sdk/integrations/rq.py"}]}