We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
I can‘t stop a task by its task_id
[2018-12-02 23:53:58,955: INFO/MainProcess] Received task: tasks.add[bb1fe102-c1f9-4361-9370-1129900c0d52]
[2018-12-02 23:54:02,479: INFO/MainProcess] Terminating bb1fe102-c1f9-4361-9370-1129900c0d52 (Signals.SIGTERM)
[2018-12-02 23:54:02,490: ERROR/MainProcess] pidbox command error: NotImplementedError("<class 'celery.concurrency.eventlet.TaskPool'> does not implement kill_job",)
Traceback (most recent call last):
  File "d:\envs\aidcs\lib\site-packages\kombu\pidbox.py", line 101, in dispatch
    reply = handle(method, arguments)
  File "d:\envs\aidcs\lib\site-packages\kombu\pidbox.py", line 122, in handle_cast
    return self.handle(method, arguments)
  File "d:\envs\aidcs\lib\site-packages\kombu\pidbox.py", line 116, in handle
    return self.handlers[method](self.state, **arguments)
  File "d:\envs\aidcs\lib\site-packages\celery\worker\control.py", line 163, in revoke
    request.terminate(state.consumer.pool, signal=signum)
  File "d:\envs\aidcs\lib\site-packages\celery\worker\request.py", line 249, in terminate
    pool.terminate_job(self.worker_pid, signal)
  File "d:\envs\aidcs\lib\site-packages\celery\concurrency\base.py", line 115, in terminate_job
    '{0} does not implement kill_job'.format(type(self)))
NotImplementedError: <class 'celery.concurrency.eventlet.TaskPool'> does not implement kill_job
[2018-12-02 23:55:38,956: INFO/MainProcess] Task tasks.add[bb1fe102-c1f9-4361-9370-1129900c0d52] succeeded in 100.0s: 8




this is my main code:

from celery.app.control import Control
from tasks import add, app

myControl=Control(app)
myControl.revoke(task_id="b11729b0-6272-4527-af9d-dc24c0ad492d", terminate=True)



finally，if i want to look at the state of the task only by task_id (just like above), how .

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `celery/concurrency/eventlet.py`
Content:
```
1 """Eventlet execution pool."""
2 import sys
3 from time import monotonic
4 
5 from kombu.asynchronous import timer as _timer
6 
7 from celery import signals
8 
9 from . import base
10 
11 __all__ = ('TaskPool',)
12 
13 W_RACE = """\
14 Celery module with %s imported before eventlet patched\
15 """
16 RACE_MODS = ('billiard.', 'celery.', 'kombu.')
17 
18 
19 #: Warn if we couldn't patch early enough,
20 #: and thread/socket depending celery modules have already been loaded.
21 for mod in (mod for mod in sys.modules if mod.startswith(RACE_MODS)):
22     for side in ('thread', 'threading', 'socket'):  # pragma: no cover
23         if getattr(mod, side, None):
24             import warnings
25             warnings.warn(RuntimeWarning(W_RACE % side))
26 
27 
28 def apply_target(target, args=(), kwargs=None, callback=None,
29                  accept_callback=None, getpid=None):
30     kwargs = {} if not kwargs else kwargs
31     return base.apply_target(target, args, kwargs, callback, accept_callback,
32                              pid=getpid())
33 
34 
35 class Timer(_timer.Timer):
36     """Eventlet Timer."""
37 
38     def __init__(self, *args, **kwargs):
39         from eventlet.greenthread import spawn_after
40         from greenlet import GreenletExit
41         super().__init__(*args, **kwargs)
42 
43         self.GreenletExit = GreenletExit
44         self._spawn_after = spawn_after
45         self._queue = set()
46 
47     def _enter(self, eta, priority, entry, **kwargs):
48         secs = max(eta - monotonic(), 0)
49         g = self._spawn_after(secs, entry)
50         self._queue.add(g)
51         g.link(self._entry_exit, entry)
52         g.entry = entry
53         g.eta = eta
54         g.priority = priority
55         g.canceled = False
56         return g
57 
58     def _entry_exit(self, g, entry):
59         try:
60             try:
61                 g.wait()
62             except self.GreenletExit:
63                 entry.cancel()
64                 g.canceled = True
65         finally:
66             self._queue.discard(g)
67 
68     def clear(self):
69         queue = self._queue
70         while queue:
71             try:
72                 queue.pop().cancel()
73             except (KeyError, self.GreenletExit):
74                 pass
75 
76     def cancel(self, tref):
77         try:
78             tref.cancel()
79         except self.GreenletExit:
80             pass
81 
82     @property
83     def queue(self):
84         return self._queue
85 
86 
87 class TaskPool(base.BasePool):
88     """Eventlet Task Pool."""
89 
90     Timer = Timer
91 
92     signal_safe = False
93     is_green = True
94     task_join_will_block = False
95     _pool = None
96     _quick_put = None
97 
98     def __init__(self, *args, **kwargs):
99         from eventlet import greenthread
100         from eventlet.greenpool import GreenPool
101         self.Pool = GreenPool
102         self.getcurrent = greenthread.getcurrent
103         self.getpid = lambda: id(greenthread.getcurrent())
104         self.spawn_n = greenthread.spawn_n
105 
106         super().__init__(*args, **kwargs)
107 
108     def on_start(self):
109         self._pool = self.Pool(self.limit)
110         signals.eventlet_pool_started.send(sender=self)
111         self._quick_put = self._pool.spawn_n
112         self._quick_apply_sig = signals.eventlet_pool_apply.send
113 
114     def on_stop(self):
115         signals.eventlet_pool_preshutdown.send(sender=self)
116         if self._pool is not None:
117             self._pool.waitall()
118         signals.eventlet_pool_postshutdown.send(sender=self)
119 
120     def on_apply(self, target, args=None, kwargs=None, callback=None,
121                  accept_callback=None, **_):
122         self._quick_apply_sig(
123             sender=self, target=target, args=args, kwargs=kwargs,
124         )
125         self._quick_put(apply_target, target, args, kwargs,
126                         callback, accept_callback,
127                         self.getpid)
128 
129     def grow(self, n=1):
130         limit = self.limit + n
131         self._pool.resize(limit)
132         self.limit = limit
133 
134     def shrink(self, n=1):
135         limit = self.limit - n
136         self._pool.resize(limit)
137         self.limit = limit
138 
139     def _get_info(self):
140         info = super()._get_info()
141         info.update({
142             'max-concurrency': self.limit,
143             'free-threads': self._pool.free(),
144             'running-threads': self._pool.running(),
145         })
146         return info
147
```
--- 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/celery/concurrency/eventlet.py b/celery/concurrency/eventlet.py
--- a/celery/concurrency/eventlet.py
+++ b/celery/concurrency/eventlet.py
@@ -2,6 +2,7 @@
 import sys
 from time import monotonic
 
+from greenlet import GreenletExit
 from kombu.asynchronous import timer as _timer
 
 from celery import signals
@@ -93,6 +94,7 @@
     is_green = True
     task_join_will_block = False
     _pool = None
+    _pool_map = None
     _quick_put = None
 
     def __init__(self, *args, **kwargs):
@@ -107,8 +109,9 @@
 
     def on_start(self):
         self._pool = self.Pool(self.limit)
+        self._pool_map = {}
         signals.eventlet_pool_started.send(sender=self)
-        self._quick_put = self._pool.spawn_n
+        self._quick_put = self._pool.spawn
         self._quick_apply_sig = signals.eventlet_pool_apply.send
 
     def on_stop(self):
@@ -119,12 +122,17 @@
 
     def on_apply(self, target, args=None, kwargs=None, callback=None,
                  accept_callback=None, **_):
-        self._quick_apply_sig(
-            sender=self, target=target, args=args, kwargs=kwargs,
+        target = TaskPool._make_killable_target(target)
+        self._quick_apply_sig(sender=self, target=target, args=args, kwargs=kwargs,)
+        greenlet = self._quick_put(
+            apply_target,
+            target, args,
+            kwargs,
+            callback,
+            accept_callback,
+            self.getpid
         )
-        self._quick_put(apply_target, target, args, kwargs,
-                        callback, accept_callback,
-                        self.getpid)
+        self._add_to_pool_map(id(greenlet), greenlet)
 
     def grow(self, n=1):
         limit = self.limit + n
@@ -136,6 +144,12 @@
         self._pool.resize(limit)
         self.limit = limit
 
+    def terminate_job(self, pid, signal=None):
+        if pid in self._pool_map.keys():
+            greenlet = self._pool_map[pid]
+            greenlet.kill()
+            greenlet.wait()
+
     def _get_info(self):
         info = super()._get_info()
         info.update({
@@ -144,3 +158,24 @@
             'running-threads': self._pool.running(),
         })
         return info
+
+    @staticmethod
+    def _make_killable_target(target):
+        def killable_target(*args, **kwargs):
+            try:
+                return target(*args, **kwargs)
+            except GreenletExit:
+                return (False, None, None)
+        return killable_target
+
+    def _add_to_pool_map(self, pid, greenlet):
+        self._pool_map[pid] = greenlet
+        greenlet.link(
+            TaskPool._cleanup_after_job_finish,
+            self._pool_map,
+            pid
+        )
+
+    @staticmethod
+    def _cleanup_after_job_finish(greenlet, pool_map, pid):
+        del pool_map[pid]

{"golden_diff": "diff --git a/celery/concurrency/eventlet.py b/celery/concurrency/eventlet.py\n--- a/celery/concurrency/eventlet.py\n+++ b/celery/concurrency/eventlet.py\n@@ -2,6 +2,7 @@\n import sys\n from time import monotonic\n \n+from greenlet import GreenletExit\n from kombu.asynchronous import timer as _timer\n \n from celery import signals\n@@ -93,6 +94,7 @@\n     is_green = True\n     task_join_will_block = False\n     _pool = None\n+    _pool_map = None\n     _quick_put = None\n \n     def __init__(self, *args, **kwargs):\n@@ -107,8 +109,9 @@\n \n     def on_start(self):\n         self._pool = self.Pool(self.limit)\n+        self._pool_map = {}\n         signals.eventlet_pool_started.send(sender=self)\n-        self._quick_put = self._pool.spawn_n\n+        self._quick_put = self._pool.spawn\n         self._quick_apply_sig = signals.eventlet_pool_apply.send\n \n     def on_stop(self):\n@@ -119,12 +122,17 @@\n \n     def on_apply(self, target, args=None, kwargs=None, callback=None,\n                  accept_callback=None, **_):\n-        self._quick_apply_sig(\n-            sender=self, target=target, args=args, kwargs=kwargs,\n+        target = TaskPool._make_killable_target(target)\n+        self._quick_apply_sig(sender=self, target=target, args=args, kwargs=kwargs,)\n+        greenlet = self._quick_put(\n+            apply_target,\n+            target, args,\n+            kwargs,\n+            callback,\n+            accept_callback,\n+            self.getpid\n         )\n-        self._quick_put(apply_target, target, args, kwargs,\n-                        callback, accept_callback,\n-                        self.getpid)\n+        self._add_to_pool_map(id(greenlet), greenlet)\n \n     def grow(self, n=1):\n         limit = self.limit + n\n@@ -136,6 +144,12 @@\n         self._pool.resize(limit)\n         self.limit = limit\n \n+    def terminate_job(self, pid, signal=None):\n+        if pid in self._pool_map.keys():\n+            greenlet = self._pool_map[pid]\n+            greenlet.kill()\n+            greenlet.wait()\n+\n     def _get_info(self):\n         info = super()._get_info()\n         info.update({\n@@ -144,3 +158,24 @@\n             'running-threads': self._pool.running(),\n         })\n         return info\n+\n+    @staticmethod\n+    def _make_killable_target(target):\n+        def killable_target(*args, **kwargs):\n+            try:\n+                return target(*args, **kwargs)\n+            except GreenletExit:\n+                return (False, None, None)\n+        return killable_target\n+\n+    def _add_to_pool_map(self, pid, greenlet):\n+        self._pool_map[pid] = greenlet\n+        greenlet.link(\n+            TaskPool._cleanup_after_job_finish,\n+            self._pool_map,\n+            pid\n+        )\n+\n+    @staticmethod\n+    def _cleanup_after_job_finish(greenlet, pool_map, pid):\n+        del pool_map[pid]\n", "issue": "I can\u2018t stop a task by its task_id\n[2018-12-02 23:53:58,955: INFO/MainProcess] Received task: tasks.add[bb1fe102-c1f9-4361-9370-1129900c0d52]\r\n[2018-12-02 23:54:02,479: INFO/MainProcess] Terminating bb1fe102-c1f9-4361-9370-1129900c0d52 (Signals.SIGTERM)\r\n[2018-12-02 23:54:02,490: ERROR/MainProcess] pidbox command error: NotImplementedError(\"<class 'celery.concurrency.eventlet.TaskPool'> does not implement kill_job\",)\r\nTraceback (most recent call last):\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\kombu\\pidbox.py\", line 101, in dispatch\r\n    reply = handle(method, arguments)\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\kombu\\pidbox.py\", line 122, in handle_cast\r\n    return self.handle(method, arguments)\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\kombu\\pidbox.py\", line 116, in handle\r\n    return self.handlers[method](self.state, **arguments)\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\celery\\worker\\control.py\", line 163, in revoke\r\n    request.terminate(state.consumer.pool, signal=signum)\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\celery\\worker\\request.py\", line 249, in terminate\r\n    pool.terminate_job(self.worker_pid, signal)\r\n  File \"d:\\envs\\aidcs\\lib\\site-packages\\celery\\concurrency\\base.py\", line 115, in terminate_job\r\n    '{0} does not implement kill_job'.format(type(self)))\r\nNotImplementedError: <class 'celery.concurrency.eventlet.TaskPool'> does not implement kill_job\r\n[2018-12-02 23:55:38,956: INFO/MainProcess] Task tasks.add[bb1fe102-c1f9-4361-9370-1129900c0d52] succeeded in 100.0s: 8\r\n\r\n\r\n\r\n\r\nthis is my main code:\r\n\r\nfrom celery.app.control import Control\r\nfrom tasks import add, app\r\n\r\nmyControl=Control(app)\r\nmyControl.revoke(task_id=\"b11729b0-6272-4527-af9d-dc24c0ad492d\", terminate=True)\r\n\r\n\r\n\r\nfinally\uff0cif i want to look at the state of the task only by task_id (just like above), how .\n", "before_files": [{"content": "\"\"\"Eventlet execution pool.\"\"\"\nimport sys\nfrom time import monotonic\n\nfrom kombu.asynchronous import timer as _timer\n\nfrom celery import signals\n\nfrom . import base\n\n__all__ = ('TaskPool',)\n\nW_RACE = \"\"\"\\\nCelery module with %s imported before eventlet patched\\\n\"\"\"\nRACE_MODS = ('billiard.', 'celery.', 'kombu.')\n\n\n#: Warn if we couldn't patch early enough,\n#: and thread/socket depending celery modules have already been loaded.\nfor mod in (mod for mod in sys.modules if mod.startswith(RACE_MODS)):\n    for side in ('thread', 'threading', 'socket'):  # pragma: no cover\n        if getattr(mod, side, None):\n            import warnings\n            warnings.warn(RuntimeWarning(W_RACE % side))\n\n\ndef apply_target(target, args=(), kwargs=None, callback=None,\n                 accept_callback=None, getpid=None):\n    kwargs = {} if not kwargs else kwargs\n    return base.apply_target(target, args, kwargs, callback, accept_callback,\n                             pid=getpid())\n\n\nclass Timer(_timer.Timer):\n    \"\"\"Eventlet Timer.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        from eventlet.greenthread import spawn_after\n        from greenlet import GreenletExit\n        super().__init__(*args, **kwargs)\n\n        self.GreenletExit = GreenletExit\n        self._spawn_after = spawn_after\n        self._queue = set()\n\n    def _enter(self, eta, priority, entry, **kwargs):\n        secs = max(eta - monotonic(), 0)\n        g = self._spawn_after(secs, entry)\n        self._queue.add(g)\n        g.link(self._entry_exit, entry)\n        g.entry = entry\n        g.eta = eta\n        g.priority = priority\n        g.canceled = False\n        return g\n\n    def _entry_exit(self, g, entry):\n        try:\n            try:\n                g.wait()\n            except self.GreenletExit:\n                entry.cancel()\n                g.canceled = True\n        finally:\n            self._queue.discard(g)\n\n    def clear(self):\n        queue = self._queue\n        while queue:\n            try:\n                queue.pop().cancel()\n            except (KeyError, self.GreenletExit):\n                pass\n\n    def cancel(self, tref):\n        try:\n            tref.cancel()\n        except self.GreenletExit:\n            pass\n\n    @property\n    def queue(self):\n        return self._queue\n\n\nclass TaskPool(base.BasePool):\n    \"\"\"Eventlet Task Pool.\"\"\"\n\n    Timer = Timer\n\n    signal_safe = False\n    is_green = True\n    task_join_will_block = False\n    _pool = None\n    _quick_put = None\n\n    def __init__(self, *args, **kwargs):\n        from eventlet import greenthread\n        from eventlet.greenpool import GreenPool\n        self.Pool = GreenPool\n        self.getcurrent = greenthread.getcurrent\n        self.getpid = lambda: id(greenthread.getcurrent())\n        self.spawn_n = greenthread.spawn_n\n\n        super().__init__(*args, **kwargs)\n\n    def on_start(self):\n        self._pool = self.Pool(self.limit)\n        signals.eventlet_pool_started.send(sender=self)\n        self._quick_put = self._pool.spawn_n\n        self._quick_apply_sig = signals.eventlet_pool_apply.send\n\n    def on_stop(self):\n        signals.eventlet_pool_preshutdown.send(sender=self)\n        if self._pool is not None:\n            self._pool.waitall()\n        signals.eventlet_pool_postshutdown.send(sender=self)\n\n    def on_apply(self, target, args=None, kwargs=None, callback=None,\n                 accept_callback=None, **_):\n        self._quick_apply_sig(\n            sender=self, target=target, args=args, kwargs=kwargs,\n        )\n        self._quick_put(apply_target, target, args, kwargs,\n                        callback, accept_callback,\n                        self.getpid)\n\n    def grow(self, n=1):\n        limit = self.limit + n\n        self._pool.resize(limit)\n        self.limit = limit\n\n    def shrink(self, n=1):\n        limit = self.limit - n\n        self._pool.resize(limit)\n        self.limit = limit\n\n    def _get_info(self):\n        info = super()._get_info()\n        info.update({\n            'max-concurrency': self.limit,\n            'free-threads': self._pool.free(),\n            'running-threads': self._pool.running(),\n        })\n        return info\n", "path": "celery/concurrency/eventlet.py"}], "after_files": [{"content": "\"\"\"Eventlet execution pool.\"\"\"\nimport sys\nfrom time import monotonic\n\nfrom greenlet import GreenletExit\nfrom kombu.asynchronous import timer as _timer\n\nfrom celery import signals\n\nfrom . import base\n\n__all__ = ('TaskPool',)\n\nW_RACE = \"\"\"\\\nCelery module with %s imported before eventlet patched\\\n\"\"\"\nRACE_MODS = ('billiard.', 'celery.', 'kombu.')\n\n\n#: Warn if we couldn't patch early enough,\n#: and thread/socket depending celery modules have already been loaded.\nfor mod in (mod for mod in sys.modules if mod.startswith(RACE_MODS)):\n    for side in ('thread', 'threading', 'socket'):  # pragma: no cover\n        if getattr(mod, side, None):\n            import warnings\n            warnings.warn(RuntimeWarning(W_RACE % side))\n\n\ndef apply_target(target, args=(), kwargs=None, callback=None,\n                 accept_callback=None, getpid=None):\n    kwargs = {} if not kwargs else kwargs\n    return base.apply_target(target, args, kwargs, callback, accept_callback,\n                             pid=getpid())\n\n\nclass Timer(_timer.Timer):\n    \"\"\"Eventlet Timer.\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        from eventlet.greenthread import spawn_after\n        from greenlet import GreenletExit\n        super().__init__(*args, **kwargs)\n\n        self.GreenletExit = GreenletExit\n        self._spawn_after = spawn_after\n        self._queue = set()\n\n    def _enter(self, eta, priority, entry, **kwargs):\n        secs = max(eta - monotonic(), 0)\n        g = self._spawn_after(secs, entry)\n        self._queue.add(g)\n        g.link(self._entry_exit, entry)\n        g.entry = entry\n        g.eta = eta\n        g.priority = priority\n        g.canceled = False\n        return g\n\n    def _entry_exit(self, g, entry):\n        try:\n            try:\n                g.wait()\n            except self.GreenletExit:\n                entry.cancel()\n                g.canceled = True\n        finally:\n            self._queue.discard(g)\n\n    def clear(self):\n        queue = self._queue\n        while queue:\n            try:\n                queue.pop().cancel()\n            except (KeyError, self.GreenletExit):\n                pass\n\n    def cancel(self, tref):\n        try:\n            tref.cancel()\n        except self.GreenletExit:\n            pass\n\n    @property\n    def queue(self):\n        return self._queue\n\n\nclass TaskPool(base.BasePool):\n    \"\"\"Eventlet Task Pool.\"\"\"\n\n    Timer = Timer\n\n    signal_safe = False\n    is_green = True\n    task_join_will_block = False\n    _pool = None\n    _pool_map = None\n    _quick_put = None\n\n    def __init__(self, *args, **kwargs):\n        from eventlet import greenthread\n        from eventlet.greenpool import GreenPool\n        self.Pool = GreenPool\n        self.getcurrent = greenthread.getcurrent\n        self.getpid = lambda: id(greenthread.getcurrent())\n        self.spawn_n = greenthread.spawn_n\n\n        super().__init__(*args, **kwargs)\n\n    def on_start(self):\n        self._pool = self.Pool(self.limit)\n        self._pool_map = {}\n        signals.eventlet_pool_started.send(sender=self)\n        self._quick_put = self._pool.spawn\n        self._quick_apply_sig = signals.eventlet_pool_apply.send\n\n    def on_stop(self):\n        signals.eventlet_pool_preshutdown.send(sender=self)\n        if self._pool is not None:\n            self._pool.waitall()\n        signals.eventlet_pool_postshutdown.send(sender=self)\n\n    def on_apply(self, target, args=None, kwargs=None, callback=None,\n                 accept_callback=None, **_):\n        target = TaskPool._make_killable_target(target)\n        self._quick_apply_sig(sender=self, target=target, args=args, kwargs=kwargs,)\n        greenlet = self._quick_put(\n            apply_target,\n            target, args,\n            kwargs,\n            callback,\n            accept_callback,\n            self.getpid\n        )\n        self._add_to_pool_map(id(greenlet), greenlet)\n\n    def grow(self, n=1):\n        limit = self.limit + n\n        self._pool.resize(limit)\n        self.limit = limit\n\n    def shrink(self, n=1):\n        limit = self.limit - n\n        self._pool.resize(limit)\n        self.limit = limit\n\n    def terminate_job(self, pid, signal=None):\n        if pid in self._pool_map.keys():\n            greenlet = self._pool_map[pid]\n            greenlet.kill()\n            greenlet.wait()\n\n    def _get_info(self):\n        info = super()._get_info()\n        info.update({\n            'max-concurrency': self.limit,\n            'free-threads': self._pool.free(),\n            'running-threads': self._pool.running(),\n        })\n        return info\n\n    @staticmethod\n    def _make_killable_target(target):\n        def killable_target(*args, **kwargs):\n            try:\n                return target(*args, **kwargs)\n            except GreenletExit:\n                return (False, None, None)\n        return killable_target\n\n    def _add_to_pool_map(self, pid, greenlet):\n        self._pool_map[pid] = greenlet\n        greenlet.link(\n            TaskPool._cleanup_after_job_finish,\n            self._pool_map,\n            pid\n        )\n\n    @staticmethod\n    def _cleanup_after_job_finish(greenlet, pool_map, pid):\n        del pool_map[pid]\n", "path": "celery/concurrency/eventlet.py"}]}