Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch KI protection default from "unprotected" to "protected" #1567

Merged
merged 1 commit into from
Jun 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions docs/source/reference-lowlevel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,15 @@ delivered).
So that's great, but – how do we know whether we're in one of the
sensitive parts of the program or not?

This is determined on a function-by-function basis. By default, a
function is protected if its caller is, and not if its caller isn't;
this is helpful because it means you only need to override the
defaults at places where you transition from protected code to
unprotected code or vice-versa.
This is determined on a function-by-function basis. By default:

- The top-level function in regular user tasks is unprotected.
- The top-level function in system tasks is protected.
- If a function doesn't specify otherwise, then it inherits the
protection state of its caller.

This means you only need to override the defaults at places where you
transition from protected code to unprotected code or vice-versa.

These transitions are accomplished using two function decorators:

Expand Down
2 changes: 1 addition & 1 deletion trio/_core/_ki.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def ki_protection_enabled(frame):
if frame.f_code.co_name == "__del__":
return True
frame = frame.f_back
return False
return True


def currently_ki_protected():
Expand Down
1 change: 0 additions & 1 deletion trio/_core/_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -1678,7 +1678,6 @@ def run(
system_context=system_context,
)
GLOBAL_RUN_CONTEXT.runner = runner
locals()[LOCALS_KEY_KI_PROTECTION_ENABLED] = True

# KI handling goes outside the core try/except/finally to avoid a window
# where KeyboardInterrupt would be allowed and converted into an
Expand Down
13 changes: 10 additions & 3 deletions trio/_core/tests/test_ki.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,8 @@ async def agen_unprotected3():


# Test the case where there's no magic local anywhere in the call stack
def test_ki_enabled_out_of_context():
assert not _core.currently_ki_protected()
def test_ki_disabled_out_of_context():
assert _core.currently_ki_protected()


def test_ki_disabled_in_del():
Expand All @@ -234,8 +234,15 @@ def __del__():
assert _core.currently_ki_protected()
assert nestedfunction()

@_core.disable_ki_protection
def outerfunction():
assert not _core.currently_ki_protected()
assert not nestedfunction()
__del__()

__del__()
assert not nestedfunction()
outerfunction()
assert nestedfunction()


def test_ki_protection_works():
Expand Down