greenlet.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. # Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
  2. from __future__ import absolute_import
  3. import sys
  4. from greenlet import greenlet
  5. from gevent._compat import PY3
  6. from gevent._compat import PYPY
  7. from gevent._compat import reraise
  8. from gevent._util import Lazy
  9. from gevent._tblib import dump_traceback
  10. from gevent._tblib import load_traceback
  11. from gevent.hub import GreenletExit
  12. from gevent.hub import InvalidSwitchError
  13. from gevent.hub import Waiter
  14. from gevent.hub import get_hub
  15. from gevent.hub import getcurrent
  16. from gevent.hub import iwait
  17. from gevent.hub import wait
  18. from gevent.timeout import Timeout
  19. from collections import deque
  20. __all__ = [
  21. 'Greenlet',
  22. 'joinall',
  23. 'killall',
  24. ]
  25. if PYPY:
  26. import _continuation # pylint:disable=import-error
  27. _continulet = _continuation.continulet
  28. class SpawnedLink(object):
  29. """A wrapper around link that calls it in another greenlet.
  30. Can be called only from main loop.
  31. """
  32. __slots__ = ['callback']
  33. def __init__(self, callback):
  34. if not callable(callback):
  35. raise TypeError("Expected callable: %r" % (callback, ))
  36. self.callback = callback
  37. def __call__(self, source):
  38. g = greenlet(self.callback, get_hub())
  39. g.switch(source)
  40. def __hash__(self):
  41. return hash(self.callback)
  42. def __eq__(self, other):
  43. return self.callback == getattr(other, 'callback', other)
  44. def __str__(self):
  45. return str(self.callback)
  46. def __repr__(self):
  47. return repr(self.callback)
  48. def __getattr__(self, item):
  49. assert item != 'callback'
  50. return getattr(self.callback, item)
  51. class SuccessSpawnedLink(SpawnedLink):
  52. """A wrapper around link that calls it in another greenlet only if source succeed.
  53. Can be called only from main loop.
  54. """
  55. __slots__ = []
  56. def __call__(self, source):
  57. if source.successful():
  58. return SpawnedLink.__call__(self, source)
  59. class FailureSpawnedLink(SpawnedLink):
  60. """A wrapper around link that calls it in another greenlet only if source failed.
  61. Can be called only from main loop.
  62. """
  63. __slots__ = []
  64. def __call__(self, source):
  65. if not source.successful():
  66. return SpawnedLink.__call__(self, source)
  67. class Greenlet(greenlet):
  68. """A light-weight cooperatively-scheduled execution unit.
  69. """
  70. # pylint:disable=too-many-public-methods,too-many-instance-attributes
  71. value = None
  72. _exc_info = ()
  73. _notifier = None
  74. #: An event, such as a timer or a callback that fires. It is established in
  75. #: start() and start_later() as those two objects, respectively.
  76. #: Once this becomes non-None, the Greenlet cannot be started again. Conversely,
  77. #: kill() and throw() check for non-None to determine if this object has ever been
  78. #: scheduled for starting. A placeholder _dummy_event is assigned by them to prevent
  79. #: the greenlet from being started in the future, if necessary.
  80. _start_event = None
  81. args = ()
  82. _kwargs = None
  83. def __init__(self, run=None, *args, **kwargs):
  84. """
  85. Greenlet constructor.
  86. :param args: The arguments passed to the ``run`` function.
  87. :param kwargs: The keyword arguments passed to the ``run`` function.
  88. :keyword run: The callable object to run. If not given, this object's
  89. `_run` method will be invoked (typically defined by subclasses).
  90. .. versionchanged:: 1.1b1
  91. The ``run`` argument to the constructor is now verified to be a callable
  92. object. Previously, passing a non-callable object would fail after the greenlet
  93. was spawned.
  94. """
  95. # greenlet.greenlet(run=None, parent=None)
  96. # Calling it with both positional arguments instead of a keyword
  97. # argument (parent=get_hub()) speeds up creation of this object ~30%:
  98. # python -m timeit -s 'import gevent' 'gevent.Greenlet()'
  99. # Python 3.5: 2.70usec with keywords vs 1.94usec with positional
  100. # Python 3.4: 2.32usec with keywords vs 1.74usec with positional
  101. # Python 3.3: 2.55usec with keywords vs 1.92usec with positional
  102. # Python 2.7: 1.73usec with keywords vs 1.40usec with positional
  103. greenlet.__init__(self, None, get_hub())
  104. if run is not None:
  105. self._run = run
  106. # If they didn't pass a callable at all, then they must
  107. # already have one. Note that subclassing to override the run() method
  108. # itself has never been documented or supported.
  109. if not callable(self._run):
  110. raise TypeError("The run argument or self._run must be callable")
  111. if args:
  112. self.args = args
  113. if kwargs:
  114. self._kwargs = kwargs
  115. @property
  116. def kwargs(self):
  117. return self._kwargs or {}
  118. @Lazy
  119. def _links(self):
  120. return deque()
  121. def _has_links(self):
  122. return '_links' in self.__dict__ and self._links
  123. def _raise_exception(self):
  124. reraise(*self.exc_info)
  125. @property
  126. def loop(self):
  127. # needed by killall
  128. return self.parent.loop
  129. def __bool__(self):
  130. return self._start_event is not None and self._exc_info is Greenlet._exc_info
  131. __nonzero__ = __bool__
  132. ### Lifecycle
  133. if PYPY:
  134. # oops - pypy's .dead relies on __nonzero__ which we overriden above
  135. @property
  136. def dead(self):
  137. if self._greenlet__main:
  138. return False
  139. if self.__start_cancelled_by_kill or self.__started_but_aborted:
  140. return True
  141. return self._greenlet__started and not _continulet.is_pending(self)
  142. else:
  143. @property
  144. def dead(self):
  145. return self.__start_cancelled_by_kill or self.__started_but_aborted or greenlet.dead.__get__(self)
  146. @property
  147. def __never_started_or_killed(self):
  148. return self._start_event is None
  149. @property
  150. def __start_pending(self):
  151. return (self._start_event is not None
  152. and (self._start_event.pending or getattr(self._start_event, 'active', False)))
  153. @property
  154. def __start_cancelled_by_kill(self):
  155. return self._start_event is _cancelled_start_event
  156. @property
  157. def __start_completed(self):
  158. return self._start_event is _start_completed_event
  159. @property
  160. def __started_but_aborted(self):
  161. return (not self.__never_started_or_killed # we have been started or killed
  162. and not self.__start_cancelled_by_kill # we weren't killed, so we must have been started
  163. and not self.__start_completed # the start never completed
  164. and not self.__start_pending) # and we're not pending, so we must have been aborted
  165. def __cancel_start(self):
  166. if self._start_event is None:
  167. # prevent self from ever being started in the future
  168. self._start_event = _cancelled_start_event
  169. # cancel any pending start event
  170. # NOTE: If this was a real pending start event, this will leave a
  171. # "dangling" callback/timer object in the hub.loop.callbacks list;
  172. # depending on where we are in the event loop, it may even be in a local
  173. # variable copy of that list (in _run_callbacks). This isn't a problem,
  174. # except for the leak-tests.
  175. self._start_event.stop()
  176. def __handle_death_before_start(self, *args):
  177. # args is (t, v, tb) or simply t or v
  178. if self._exc_info is Greenlet._exc_info and self.dead:
  179. # the greenlet was never switched to before and it will never be, _report_error was not called
  180. # the result was not set and the links weren't notified. let's do it here.
  181. # checking that self.dead is true is essential, because throw() does not necessarily kill the greenlet
  182. # (if the exception raised by throw() is caught somewhere inside the greenlet).
  183. if len(args) == 1:
  184. arg = args[0]
  185. #if isinstance(arg, type):
  186. if type(arg) is type(Exception):
  187. args = (arg, arg(), None)
  188. else:
  189. args = (type(arg), arg, None)
  190. elif not args:
  191. args = (GreenletExit, GreenletExit(), None)
  192. self._report_error(args)
  193. @property
  194. def started(self):
  195. # DEPRECATED
  196. return bool(self)
  197. def ready(self):
  198. """
  199. Return a true value if and only if the greenlet has finished
  200. execution.
  201. .. versionchanged:: 1.1
  202. This function is only guaranteed to return true or false *values*, not
  203. necessarily the literal constants ``True`` or ``False``.
  204. """
  205. return self.dead or self._exc_info
  206. def successful(self):
  207. """
  208. Return a true value if and only if the greenlet has finished execution
  209. successfully, that is, without raising an error.
  210. .. tip:: A greenlet that has been killed with the default
  211. :class:`GreenletExit` exception is considered successful.
  212. That is, ``GreenletExit`` is not considered an error.
  213. .. note:: This function is only guaranteed to return true or false *values*,
  214. not necessarily the literal constants ``True`` or ``False``.
  215. """
  216. return self._exc_info and self._exc_info[1] is None
  217. def __repr__(self):
  218. classname = self.__class__.__name__
  219. result = '<%s at %s' % (classname, hex(id(self)))
  220. formatted = self._formatinfo()
  221. if formatted:
  222. result += ': ' + formatted
  223. return result + '>'
  224. _formatted_info = None
  225. def _formatinfo(self):
  226. info = self._formatted_info
  227. if info is not None:
  228. return info
  229. try:
  230. result = getfuncname(self.__dict__['_run'])
  231. except Exception: # pylint:disable=broad-except
  232. # Don't cache
  233. return ''
  234. args = []
  235. if self.args:
  236. args = [repr(x)[:50] for x in self.args]
  237. if self._kwargs:
  238. args.extend(['%s=%s' % (key, repr(value)[:50]) for (key, value) in self._kwargs.items()])
  239. if args:
  240. result += '(' + ', '.join(args) + ')'
  241. # it is important to save the result here, because once the greenlet exits '_run' attribute will be removed
  242. self._formatted_info = result
  243. return result
  244. @property
  245. def exception(self):
  246. """Holds the exception instance raised by the function if the greenlet has finished with an error.
  247. Otherwise ``None``.
  248. """
  249. return self._exc_info[1] if self._exc_info else None
  250. @property
  251. def exc_info(self):
  252. """
  253. Holds the exc_info three-tuple raised by the function if the
  254. greenlet finished with an error. Otherwise a false value.
  255. .. note:: This is a provisional API and may change.
  256. .. versionadded:: 1.1
  257. """
  258. e = self._exc_info
  259. if e and e[0] is not None:
  260. return (e[0], e[1], load_traceback(e[2]))
  261. def throw(self, *args):
  262. """Immediatelly switch into the greenlet and raise an exception in it.
  263. Should only be called from the HUB, otherwise the current greenlet is left unscheduled forever.
  264. To raise an exception in a safe manner from any greenlet, use :meth:`kill`.
  265. If a greenlet was started but never switched to yet, then also
  266. a) cancel the event that will start it
  267. b) fire the notifications as if an exception was raised in a greenlet
  268. """
  269. self.__cancel_start()
  270. try:
  271. if not self.dead:
  272. # Prevent switching into a greenlet *at all* if we had never
  273. # started it. Usually this is the same thing that happens by throwing,
  274. # but if this is done from the hub with nothing else running, prevents a
  275. # LoopExit.
  276. greenlet.throw(self, *args)
  277. finally:
  278. self.__handle_death_before_start(*args)
  279. def start(self):
  280. """Schedule the greenlet to run in this loop iteration"""
  281. if self._start_event is None:
  282. self._start_event = self.parent.loop.run_callback(self.switch)
  283. def start_later(self, seconds):
  284. """Schedule the greenlet to run in the future loop iteration *seconds* later"""
  285. if self._start_event is None:
  286. self._start_event = self.parent.loop.timer(seconds)
  287. self._start_event.start(self.switch)
  288. @classmethod
  289. def spawn(cls, *args, **kwargs):
  290. """
  291. Create a new :class:`Greenlet` object and schedule it to run ``function(*args, **kwargs)``.
  292. This can be used as ``gevent.spawn`` or ``Greenlet.spawn``.
  293. The arguments are passed to :meth:`Greenlet.__init__`.
  294. .. versionchanged:: 1.1b1
  295. If a *function* is given that is not callable, immediately raise a :exc:`TypeError`
  296. instead of spawning a greenlet that will raise an uncaught TypeError.
  297. """
  298. g = cls(*args, **kwargs)
  299. g.start()
  300. return g
  301. @classmethod
  302. def spawn_later(cls, seconds, *args, **kwargs):
  303. """
  304. Create and return a new Greenlet object scheduled to run ``function(*args, **kwargs)``
  305. in the future loop iteration *seconds* later. This can be used as ``Greenlet.spawn_later``
  306. or ``gevent.spawn_later``.
  307. The arguments are passed to :meth:`Greenlet.__init__`.
  308. .. versionchanged:: 1.1b1
  309. If an argument that's meant to be a function (the first argument in *args*, or the ``run`` keyword )
  310. is given to this classmethod (and not a classmethod of a subclass),
  311. it is verified to be callable. Previously, the spawned greenlet would have failed
  312. when it started running.
  313. """
  314. if cls is Greenlet and not args and 'run' not in kwargs:
  315. raise TypeError("")
  316. g = cls(*args, **kwargs)
  317. g.start_later(seconds)
  318. return g
  319. def kill(self, exception=GreenletExit, block=True, timeout=None):
  320. """
  321. Raise the ``exception`` in the greenlet.
  322. If ``block`` is ``True`` (the default), wait until the greenlet dies or the optional timeout expires.
  323. If block is ``False``, the current greenlet is not unscheduled.
  324. The function always returns ``None`` and never raises an error.
  325. .. note::
  326. Depending on what this greenlet is executing and the state
  327. of the event loop, the exception may or may not be raised
  328. immediately when this greenlet resumes execution. It may
  329. be raised on a subsequent green call, or, if this greenlet
  330. exits before making such a call, it may not be raised at
  331. all. As of 1.1, an example where the exception is raised
  332. later is if this greenlet had called :func:`sleep(0)
  333. <gevent.sleep>`; an example where the exception is raised
  334. immediately is if this greenlet had called
  335. :func:`sleep(0.1) <gevent.sleep>`.
  336. .. caution::
  337. Use care when killing greenlets. If the code executing is not
  338. exception safe (e.g., makes proper use of ``finally``) then an
  339. unexpected exception could result in corrupted state.
  340. See also :func:`gevent.kill`.
  341. :keyword type exception: The type of exception to raise in the greenlet. The default
  342. is :class:`GreenletExit`, which indicates a :meth:`successful` completion
  343. of the greenlet.
  344. .. versionchanged:: 0.13.0
  345. *block* is now ``True`` by default.
  346. .. versionchanged:: 1.1a2
  347. If this greenlet had never been switched to, killing it will prevent it from ever being switched to.
  348. """
  349. self.__cancel_start()
  350. if self.dead:
  351. self.__handle_death_before_start(exception)
  352. else:
  353. waiter = Waiter() if block else None
  354. self.parent.loop.run_callback(_kill, self, exception, waiter)
  355. if block:
  356. waiter.get()
  357. self.join(timeout)
  358. # it should be OK to use kill() in finally or kill a greenlet from more than one place;
  359. # thus it should not raise when the greenlet is already killed (= not started)
  360. def get(self, block=True, timeout=None):
  361. """Return the result the greenlet has returned or re-raise the exception it has raised.
  362. If block is ``False``, raise :class:`gevent.Timeout` if the greenlet is still alive.
  363. If block is ``True``, unschedule the current greenlet until the result is available
  364. or the timeout expires. In the latter case, :class:`gevent.Timeout` is raised.
  365. """
  366. if self.ready():
  367. if self.successful():
  368. return self.value
  369. self._raise_exception()
  370. if not block:
  371. raise Timeout()
  372. switch = getcurrent().switch
  373. self.rawlink(switch)
  374. try:
  375. t = Timeout._start_new_or_dummy(timeout)
  376. try:
  377. result = self.parent.switch()
  378. if result is not self:
  379. raise InvalidSwitchError('Invalid switch into Greenlet.get(): %r' % (result, ))
  380. finally:
  381. t.cancel()
  382. except:
  383. # unlinking in 'except' instead of finally is an optimization:
  384. # if switch occurred normally then link was already removed in _notify_links
  385. # and there's no need to touch the links set.
  386. # Note, however, that if "Invalid switch" assert was removed and invalid switch
  387. # did happen, the link would remain, causing another invalid switch later in this greenlet.
  388. self.unlink(switch)
  389. raise
  390. if self.ready():
  391. if self.successful():
  392. return self.value
  393. self._raise_exception()
  394. def join(self, timeout=None):
  395. """Wait until the greenlet finishes or *timeout* expires.
  396. Return ``None`` regardless.
  397. """
  398. if self.ready():
  399. return
  400. switch = getcurrent().switch
  401. self.rawlink(switch)
  402. try:
  403. t = Timeout._start_new_or_dummy(timeout)
  404. try:
  405. result = self.parent.switch()
  406. if result is not self:
  407. raise InvalidSwitchError('Invalid switch into Greenlet.join(): %r' % (result, ))
  408. finally:
  409. t.cancel()
  410. except Timeout as ex:
  411. self.unlink(switch)
  412. if ex is not t:
  413. raise
  414. except:
  415. self.unlink(switch)
  416. raise
  417. def _report_result(self, result):
  418. self._exc_info = (None, None, None)
  419. self.value = result
  420. if self._has_links() and not self._notifier:
  421. self._notifier = self.parent.loop.run_callback(self._notify_links)
  422. def _report_error(self, exc_info):
  423. if isinstance(exc_info[1], GreenletExit):
  424. self._report_result(exc_info[1])
  425. return
  426. self._exc_info = exc_info[0], exc_info[1], dump_traceback(exc_info[2])
  427. if self._has_links() and not self._notifier:
  428. self._notifier = self.parent.loop.run_callback(self._notify_links)
  429. try:
  430. self.parent.handle_error(self, *exc_info)
  431. finally:
  432. del exc_info
  433. def run(self):
  434. try:
  435. self.__cancel_start()
  436. self._start_event = _start_completed_event
  437. try:
  438. result = self._run(*self.args, **self.kwargs)
  439. except: # pylint:disable=bare-except
  440. self._report_error(sys.exc_info())
  441. return
  442. self._report_result(result)
  443. finally:
  444. self.__dict__.pop('_run', None)
  445. self.__dict__.pop('args', None)
  446. self.__dict__.pop('kwargs', None)
  447. def _run(self):
  448. """Subclasses may override this method to take any number of arguments and keyword arguments.
  449. .. versionadded:: 1.1a3
  450. Previously, if no callable object was passed to the constructor, the spawned greenlet would
  451. later fail with an AttributeError.
  452. """
  453. # We usually override this in __init__
  454. # pylint: disable=method-hidden
  455. return
  456. def rawlink(self, callback):
  457. """Register a callable to be executed when the greenlet finishes execution.
  458. The *callback* will be called with this instance as an argument.
  459. .. caution:: The callable will be called in the HUB greenlet.
  460. """
  461. if not callable(callback):
  462. raise TypeError('Expected callable: %r' % (callback, ))
  463. self._links.append(callback) # pylint:disable=no-member
  464. if self.ready() and self._links and not self._notifier:
  465. self._notifier = self.parent.loop.run_callback(self._notify_links)
  466. def link(self, callback, SpawnedLink=SpawnedLink):
  467. """
  468. Link greenlet's completion to a callable.
  469. The *callback* will be called with this instance as an
  470. argument once this greenlet is dead. A callable is called in
  471. its own :class:`greenlet.greenlet` (*not* a
  472. :class:`Greenlet`).
  473. """
  474. # XXX: Is the redefinition of SpawnedLink supposed to just be an
  475. # optimization, or do people use it? It's not documented
  476. # pylint:disable=redefined-outer-name
  477. self.rawlink(SpawnedLink(callback))
  478. def unlink(self, callback):
  479. """Remove the callback set by :meth:`link` or :meth:`rawlink`"""
  480. try:
  481. self._links.remove(callback) # pylint:disable=no-member
  482. except ValueError:
  483. pass
  484. def link_value(self, callback, SpawnedLink=SuccessSpawnedLink):
  485. """
  486. Like :meth:`link` but *callback* is only notified when the greenlet
  487. has completed successfully.
  488. """
  489. # pylint:disable=redefined-outer-name
  490. self.link(callback, SpawnedLink=SpawnedLink)
  491. def link_exception(self, callback, SpawnedLink=FailureSpawnedLink):
  492. """Like :meth:`link` but *callback* is only notified when the greenlet dies because of an unhandled exception."""
  493. # pylint:disable=redefined-outer-name
  494. self.link(callback, SpawnedLink=SpawnedLink)
  495. def _notify_links(self):
  496. while self._links:
  497. link = self._links.popleft() # pylint:disable=no-member
  498. try:
  499. link(self)
  500. except: # pylint:disable=bare-except
  501. self.parent.handle_error((link, self), *sys.exc_info())
  502. class _dummy_event(object):
  503. pending = False
  504. active = False
  505. def stop(self):
  506. pass
  507. def start(self, cb): # pylint:disable=unused-argument
  508. raise AssertionError("Cannot start the dummy event")
  509. _cancelled_start_event = _dummy_event()
  510. _start_completed_event = _dummy_event()
  511. del _dummy_event
  512. def _kill(glet, exception, waiter):
  513. try:
  514. glet.throw(exception)
  515. except: # pylint:disable=bare-except
  516. # XXX do we need this here?
  517. glet.parent.handle_error(glet, *sys.exc_info())
  518. if waiter is not None:
  519. waiter.switch()
  520. def joinall(greenlets, timeout=None, raise_error=False, count=None):
  521. """
  522. Wait for the ``greenlets`` to finish.
  523. :param greenlets: A sequence (supporting :func:`len`) of greenlets to wait for.
  524. :keyword float timeout: If given, the maximum number of seconds to wait.
  525. :return: A sequence of the greenlets that finished before the timeout (if any)
  526. expired.
  527. """
  528. if not raise_error:
  529. return wait(greenlets, timeout=timeout, count=count)
  530. done = []
  531. for obj in iwait(greenlets, timeout=timeout, count=count):
  532. if getattr(obj, 'exception', None) is not None:
  533. if hasattr(obj, '_raise_exception'):
  534. obj._raise_exception()
  535. else:
  536. raise obj.exception
  537. done.append(obj)
  538. return done
  539. def _killall3(greenlets, exception, waiter):
  540. diehards = []
  541. for g in greenlets:
  542. if not g.dead:
  543. try:
  544. g.throw(exception)
  545. except: # pylint:disable=bare-except
  546. g.parent.handle_error(g, *sys.exc_info())
  547. if not g.dead:
  548. diehards.append(g)
  549. waiter.switch(diehards)
  550. def _killall(greenlets, exception):
  551. for g in greenlets:
  552. if not g.dead:
  553. try:
  554. g.throw(exception)
  555. except: # pylint:disable=bare-except
  556. g.parent.handle_error(g, *sys.exc_info())
  557. def killall(greenlets, exception=GreenletExit, block=True, timeout=None):
  558. """
  559. Forceably terminate all the ``greenlets`` by causing them to raise ``exception``.
  560. .. caution:: Use care when killing greenlets. If they are not prepared for exceptions,
  561. this could result in corrupted state.
  562. :param greenlets: A **bounded** iterable of the non-None greenlets to terminate.
  563. *All* the items in this iterable must be greenlets that belong to the same thread.
  564. :keyword exception: The exception to raise in the greenlets. By default this is
  565. :class:`GreenletExit`.
  566. :keyword bool block: If True (the default) then this function only returns when all the
  567. greenlets are dead; the current greenlet is unscheduled during that process.
  568. If greenlets ignore the initial exception raised in them,
  569. then they will be joined (with :func:`gevent.joinall`) and allowed to die naturally.
  570. If False, this function returns immediately and greenlets will raise
  571. the exception asynchronously.
  572. :keyword float timeout: A time in seconds to wait for greenlets to die. If given, it is
  573. only honored when ``block`` is True.
  574. :raise Timeout: If blocking and a timeout is given that elapses before
  575. all the greenlets are dead.
  576. .. versionchanged:: 1.1a2
  577. *greenlets* can be any iterable of greenlets, like an iterator or a set.
  578. Previously it had to be a list or tuple.
  579. """
  580. # support non-indexable containers like iterators or set objects
  581. greenlets = list(greenlets)
  582. if not greenlets:
  583. return
  584. loop = greenlets[0].loop
  585. if block:
  586. waiter = Waiter()
  587. loop.run_callback(_killall3, greenlets, exception, waiter)
  588. t = Timeout._start_new_or_dummy(timeout)
  589. try:
  590. alive = waiter.get()
  591. if alive:
  592. joinall(alive, raise_error=False)
  593. finally:
  594. t.cancel()
  595. else:
  596. loop.run_callback(_killall, greenlets, exception)
  597. if PY3:
  598. _meth_self = "__self__"
  599. else:
  600. _meth_self = "im_self"
  601. def getfuncname(func):
  602. if not hasattr(func, _meth_self):
  603. try:
  604. funcname = func.__name__
  605. except AttributeError:
  606. pass
  607. else:
  608. if funcname != '<lambda>':
  609. return funcname
  610. return repr(func)