Skip to content

Commit ee00b76

Browse files
committed
---
yaml --- r: 7155 b: refs/heads/master c: 110c3cc h: refs/heads/master i: 7153: 892946a 7151: 9cd3378 v: v3
1 parent a038819 commit ee00b76

File tree

6 files changed

+48
-18
lines changed

6 files changed

+48
-18
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 005e3194858785e9debae8116caedf4c14e3b727
2+
refs/heads/master: 110c3ccdcad4616fd558f248b61a4ba79d8ec86b

trunk/src/libcore/task.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export spawn_joinable;
4949
export spawn_connected;
5050
export connected_fn;
5151
export connected_task;
52+
export currently_unwinding;
5253

5354
#[abi = "rust-intrinsic"]
5455
native mod rusti {
@@ -76,6 +77,8 @@ native mod rustrt {
7677
fn migrate_alloc(alloc: *u8, target: task_id);
7778

7879
fn start_task(id: task, closure: *rust_closure);
80+
81+
fn rust_task_is_unwinding(rt: *rust_task) -> bool;
7982
}
8083

8184
/* Section: Types */
@@ -271,7 +274,7 @@ fn sleep(time_in_us: uint) {
271274
// in a snapshot.
272275
// #debug("yielding for %u us", time_in_us);
273276
rusti::task_sleep(task, time_in_us, killed);
274-
if killed {
277+
if killed && !currently_unwinding() {
275278
fail "killed";
276279
}
277280
}
@@ -337,6 +340,15 @@ Unpin the current task and future child tasks
337340
*/
338341
fn unpin() { rustrt::unpin_task(); }
339342

343+
/*
344+
Function: currently_unwinding()
345+
346+
True if we are currently unwinding after a failure.
347+
*/
348+
fn currently_unwinding() -> bool {
349+
rustrt::rust_task_is_unwinding(rustrt::rust_get_task())
350+
}
351+
340352
// Local Variables:
341353
// mode: rust;
342354
// fill-column: 78;

trunk/src/rt/rust_task.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state,
245245
running_on(-1),
246246
pinned_on(-1),
247247
local_region(&sched->srv->local_region),
248-
failed(false),
248+
unwinding(false),
249249
killed(false),
250250
propagate_failure(true),
251251
dynastack(this),
@@ -299,27 +299,27 @@ struct spawn_args {
299299

300300
struct cleanup_args {
301301
spawn_args *spargs;
302-
bool failed;
302+
bool threw_exception;
303303
};
304304

305305
void
306306
cleanup_task(cleanup_args *args) {
307307
spawn_args *a = args->spargs;
308-
bool failed = args->failed;
308+
bool threw_exception = args->threw_exception;
309309
rust_task *task = a->task;
310310

311311
cc::do_cc(task);
312312

313313
task->die();
314314

315-
if (task->killed && !failed) {
315+
if (task->killed && !threw_exception) {
316316
LOG(task, task, "Task killed during termination");
317-
failed = true;
317+
threw_exception = true;
318318
}
319319

320-
task->notify(!failed);
320+
task->notify(!threw_exception);
321321

322-
if (failed) {
322+
if (threw_exception) {
323323
#ifndef __WIN32__
324324
task->conclude_failure();
325325
#else
@@ -336,15 +336,15 @@ void task_start_wrapper(spawn_args *a)
336336
{
337337
rust_task *task = a->task;
338338

339-
bool failed = false;
339+
bool threw_exception = false;
340340
try {
341341
// The first argument is the return pointer; as the task fn
342342
// must have void return type, we can safely pass 0.
343343
a->f(0, a->envptr, a->argptr);
344344
} catch (rust_task *ex) {
345345
A(task->sched, ex == task,
346346
"Expected this task to be thrown for unwinding");
347-
failed = true;
347+
threw_exception = true;
348348
}
349349

350350
rust_opaque_closure* env = a->envptr;
@@ -357,7 +357,7 @@ void task_start_wrapper(spawn_args *a)
357357
}
358358

359359
// The cleanup work needs lots of stack
360-
cleanup_args ca = {a, failed};
360+
cleanup_args ca = {a, threw_exception};
361361
task->sched->c_context.call_shim_on_c_stack(&ca, (void*)cleanup_task);
362362

363363
task->ctx.next->swap(task->ctx);
@@ -437,11 +437,17 @@ rust_task::kill() {
437437
// run_on_resume(rust_unwind_glue);
438438
}
439439

440+
extern "C" CDECL
441+
bool rust_task_is_unwinding(rust_task *rt) {
442+
return rt->unwinding;
443+
}
444+
440445
void
441446
rust_task::fail() {
442447
// See note in ::kill() regarding who should call this.
443448
DLOG(sched, task, "task %s @0x%" PRIxPTR " failing", name, this);
444449
backtrace();
450+
unwinding = true;
445451
#ifndef __WIN32__
446452
throw this;
447453
#else
@@ -455,7 +461,6 @@ rust_task::fail() {
455461
void
456462
rust_task::conclude_failure() {
457463
fail_parent();
458-
failed = true;
459464
}
460465

461466
void

trunk/src/rt/rust_task.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
107107

108108
memory_region local_region;
109109

110-
// Indicates that the task ended in failure
111-
bool failed;
110+
// Indicates that fail() has been called and we are cleaning up.
111+
// We use this to suppress the "killed" flag during calls to yield.
112+
bool unwinding;
113+
112114
// Indicates that the task was killed and needs to unwind
113115
bool killed;
114116
bool propagate_failure;

trunk/src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ rust_ptr_eq
4343
rust_run_program
4444
rust_start
4545
rust_getcwd
46+
rust_task_is_unwinding
4647
rust_task_sleep
4748
rust_get_task
4849
set_min_stack

trunk/src/test/run-pass/task-killjoin-rsrc.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,26 @@ fn joinable(f: fn()) -> (task::task, comm::port<bool>) {
1010
resource notify(data: (comm::chan<bool>,
1111
@mutable bool)) {
1212
let (c, v) = data;
13+
#error["notify: task=%d v=%x unwinding=%b b=%b",
14+
task::get_task(),
15+
ptr::addr_of(*v) as uint,
16+
task::currently_unwinding(),
17+
*v];
1318
comm::send(c, *v);
1419
}
1520
fn wrapper(pair: (comm::chan<bool>, fn())) {
1621
let (c, f) = pair;
1722
let b = @mutable false;
23+
#error["wrapper: task=%d allocated v=%x",
24+
task::get_task(),
25+
ptr::addr_of(*b) as uint];
1826
let _r = notify((c, b));
1927
f();
2028
*b = true;
2129
}
2230
let p = comm::port();
2331
let c = comm::chan(p);
24-
let t = task::spawn((c, f), wrapper);
32+
let t = task::spawn {|| wrapper((c, f)) };
2533
ret (t, p);
2634
}
2735

@@ -34,6 +42,7 @@ fn supervised() {
3442
// Yield to make sure the supervisor joins before we
3543
// fail. This is currently not needed because the supervisor
3644
// runs first, but I can imagine that changing.
45+
#error["supervised task=%d", task::get_task()];
3746
task::yield();
3847
fail;
3948
}
@@ -42,8 +51,9 @@ fn supervisor() {
4251
// Unsupervise this task so the process doesn't return a failure status as
4352
// a result of the main task being killed.
4453
task::unsupervise();
45-
let f = supervised;
46-
join(joinable(supervised));
54+
#error["supervisor task=%d", task::get_task()];
55+
let t = joinable(supervised);
56+
join(t);
4757
}
4858

4959
fn main() {

0 commit comments

Comments
 (0)