Change:
res.recv(); } <del> #[test] #[should_fail] #[ignore(cfg(windows))] </del> <ins> #[test] #[should_fail] #[ignore(reason = "random red")] </ins> pub fn exclusive_unwrap_conflict() { let x = exclusive(~~"hello"); let x2 = ~mut Some(x.clone());

Discussion:
In core, fails maybe a few times per month. Linux x86_64. I have no further information.
alright, i don't suppose you'd happen to have any logs of the times it failed? I haven't been able to reproduce the test failing (i.e., the test function terminating successfully). Looking over the unwrap implementation I think it's basically impossible for the test to fail with a localized bug, since it's testing two linked-failure tasks who go through code that looks like this: so I think it is safe to say that exactly one of the tasks will hit the . What's more, the test case itself has the parent thread (the one the test harness will block on) block on its child using a future_result. Either the parent will hit the die above (in which case the test case will surely pass), or the child will hit it, in which case the child's failure should link to the parent through the parent's call (I checked the linked failure code to make sure taskgroup killing happens before AutoNotify messaging). So it might be just as likely the race is in getting failed out of the recv call. So far I've experimented adding delays into various parts of the unwrap implementation to see which paths this test actually exercises (the state space is not very large, so it is not a Research Problem :P ), but not seen the bug in any yet. Will continue the search another day. EDIT: reproduction successful. (I'd forgotten that there was a difference in failure semantics between when the tasks are in the main/root taskgroup and when they're running as a #[test]! Argh.) More later.
Would you believe this is the minimized test case for this bug? No unwrap involved at all. Depending on the sleep, the test will either work or not (i.e., the problem is when a failing task sends to its futureresult before the parent even starts to receive on it, the linked failure doesn't take effect). I'm not sure if this is an intended nondeterminism of , but I definitely wrote assuming it wouldn't happen that way. anyway one possible way to fix this is to change the last line of the test case to (which doesn't weaken the test case). I will meditate on this more to decide if that's the best way.

OK, what's going on here is linked failure doesn't propagate through a in the special case where the pipe has data and the task doesn't need to block for it. To "fix" this nondeterminism at its source would involve putting a check in the case of . As another example, consider this program, whose main task always succeeds. "Fixing" the nondetermism above would make this program sometimes succeed (if the parent recvs before the child sends) and sometimes fail (if the child sends and fails before the parent recvs). Introducing the extra killed check wouldn't require taking a lock (see ). But, I've always punted on the semantics of when a linked failure killing takes effect, and adding this check feels like a patchwork special-case rather than a principled semantics change. might have input on the matter?
Adding the check seems reasonable to me. In the case of failure, I think it's fine if things are somewhat nondeterministic, so I don't think it's a problem if the program above sometimes failed. What if we a sleep before ? It seems like in that case you'd want this to always fail, unless you turned off link failure.
Thanks for looking into this. I understand how misses its opportunity to fail but not why the 'assert' has any effect. This is similar to a problem I frequently run into where I expect test cases like this to work (by failing):
Yeah, those are annoying cases. It might be nice to have a spawn interface that, while letting the parent go off and do its own thing, also makes the parent block on the child (on all such children spawned this way) before actually task-exiting. This could be done with on top of a generalised interface, or it could work by stashing s inside the parent's and having the destructor wait on each one in the destructor (which is essentially a hardcoded version of how would also work).