Skip to content

Commit dac98f6

Browse files
committed
---
yaml --- r: 67534 b: refs/heads/master c: 036a6d2 h: refs/heads/master v: v3
1 parent f51940d commit dac98f6

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 880246618b6c28adc76e5e68247aa5a9302320f8
2+
refs/heads/master: 036a6d2f0080abd10521f7999af7100e5bcaaffe
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 18e3db7392d2d0697b7e27d6d986139960144d85
55
refs/heads/try: 7b78b52e602bb3ea8174f9b2006bff3315f03ef9

trunk/src/libstd/rt/kill.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,63 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Task death: asynchronous killing, linked failure, exit code propagation.
11+
/*!
12+
13+
Task death: asynchronous killing, linked failure, exit code propagation.
14+
15+
This file implements two orthogonal building-blocks for communicating failure
16+
between tasks. One is 'linked failure' or 'task killing', that is, a failing
17+
task causing other tasks to fail promptly (even those that are blocked on
18+
pipes or I/O). The other is 'exit code propagation', which affects the result
19+
observed by the parent of a task::try task that itself spawns child tasks
20+
(such as any #[test] function). In both cases the data structures live in
21+
KillHandle.
22+
23+
I. Task killing.
24+
25+
The model for killing involves two atomic flags, the "kill flag" and the
26+
"unkillable flag". Operations on the kill flag include:
27+
28+
- In the taskgroup code (task/spawn.rs), tasks store a clone of their
29+
KillHandle in their shared taskgroup. Another task in the group that fails
30+
will use that handle to call kill().
31+
- When a task blocks, it turns its ~Task into a BlockedTask by storing a
32+
the transmuted ~Task pointer inside the KillHandle's kill flag. A task
33+
trying to block and a task trying to kill it can simultaneously access the
34+
kill flag, after which the task will get scheduled and fail (no matter who
35+
wins the race). Likewise, a task trying to wake a blocked task normally and
36+
a task trying to kill it can simultaneously access the flag; only one will
37+
get the task to reschedule it.
38+
39+
Operations on the unkillable flag include:
40+
41+
- When a task becomes unkillable, it swaps on the flag to forbid any killer
42+
from waking it up while it's blocked inside the unkillable section. If a
43+
kill was already pending, the task fails instead of becoming unkillable.
44+
- When a task is done being unkillable, it restores the flag to the normal
45+
running state. If a kill was received-but-blocked during the unkillable
46+
section, the task fails at this later point.
47+
- When a task tries to kill another task, before swapping on the kill flag, it
48+
first swaps on the unkillable flag, to see if it's "allowed" to wake up the
49+
task. If it isn't, the killed task will receive the signal when it becomes
50+
killable again. (Of course, a task trying to wake the task normally (e.g.
51+
sending on a channel) does not access the unkillable flag at all.)
52+
53+
Why do we not need acquire/release barriers on any of the kill flag swaps?
54+
This is because barriers establish orderings between accesses on different
55+
memory locations, but each kill-related operation is only a swap on a single
56+
location, so atomicity is all that matters. The exception is kill(), which
57+
does a swap on both flags in sequence. kill() needs no barriers because it
58+
does not matter if its two accesses are seen reordered on another CPU: if a
59+
killer does perform both writes, it means it saw a KILL_RUNNING in the
60+
unkillable flag, which means an unkillable task will see KILL_KILLED and fail
61+
immediately (rendering the subsequent write to the kill flag unnecessary).
62+
63+
II. Exit code propagation.
64+
65+
FIXME(#7544): Decide on the ultimate model for this and document it.
66+
67+
*/
1268

1369
use cast;
1470
use cell::Cell;

0 commit comments

Comments
 (0)