Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Bliss
bliss
Commits
36a25f11
Commit
36a25f11
authored
Jul 09, 2021
by
Wout De Nolf
Browse files
docstrings
parent
d8730558
Pipeline
#50367
failed with stages
in 115 minutes and 53 seconds
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
bliss/common/greenlet_utils.py
View file @
36a25f11
...
...
@@ -15,14 +15,50 @@ logger = logging.getLogger(__name__)
class
KillMask
:
"""All exceptions which are the result of a `kill(SomeException)`
call on the greenlet in which the KillMask context is entered,
will be delayed until context exit, except for `gevent.Timeout`.
will be DELAYED until the context exit. The only exception that
is not delayed is `gevent.Timeout`.
Upon exit, only the last captured exception is re-raised.
Upon exiting the `KillMask` context, only the last captured
exception is re-raised.
Optionally we can set a limit to the number of `kill` calls
that will be delayed.
Warning: this does not delay interrupts.
that will be delayed. The prevent the possibility that a greenlet
can never be killed (see example below).
As this is entirely based on intercepting `kill` calls:
- this can never work in the main greenlet
- this only works in `BlissGreenlet` greenlets
Note: `KeyboardInterrupt` is always raised in the main greenlet,
never in other greenlets unless someone explicitely calls
`kill(KeyboardInterrupt)`. Apart from the later case, `KillMask`
does not delay `KeyboardInterrupt`.
A typical use case of `KillMask` is this:
def greenlet_main():
<setup>
try:
<body>
finally:
with KillMask(masked_kill_nb=1):
<cleanup>
We assume this code does not run in the main greenlet. Whenever
you use a cooperative call, you could receive an exception in
`greenlet_main` originating from a `kill` on the executing greenlet.
The default exception is `GreenletExit` which is a `BaseException`.
In the exception could occur in three locations (assuming they
all use cooperative calls):
1. exception in <setup>: <cleanup> is not called
2. exception in <body>: <cleanup> is called thanks to try-finally
3. exception in <cleanup>: <cleanup> is fully executed thanks to `Killmask`
If <cleanup> is blocking, the `Killmask` prevents the executing
greenlet from being killed. Hence the usage of `masked_kill_nb=1`.
The first `kill` gets intercepted but the second `kill` does not.
"""
def
__init__
(
self
,
masked_kill_nb
=-
1
):
...
...
@@ -114,7 +150,8 @@ _GeventGreenlet = greenlet.Greenlet
class
BlissGreenlet
(
_GeventGreenlet
):
"""KillMask can only work when entered in a greenlet of type `BlissGreenlet`
"""The `KillMask``context can only work when entered in
a greenlet of type `BlissGreenlet`.
"""
def
__init__
(
self
,
*
args
,
**
kw
):
...
...
@@ -160,7 +197,7 @@ class BlissGreenlet(_GeventGreenlet):
class
BlissTimeout
(
_GeventTimeout
):
"""KillMask can only work when timeouts are of type `BlissTimeout`
"""KillMask can only work when timeouts are of type `BlissTimeout`
.
"""
def
_on_expiration
(
self
,
prev_greenlet
,
ex
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment