Skip to content

Commit 13fa2c8

Browse files
committed
auto merge of #8158 : bblum/rust/task-cleanup, r=brson
r? @brson
2 parents 5542019 + 63ba633 commit 13fa2c8

File tree

9 files changed

+139
-74
lines changed

9 files changed

+139
-74
lines changed

src/libstd/rt/kill.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub struct Death {
8484
on_exit: Option<~fn(bool)>,
8585
// nesting level counter for task::unkillable calls (0 == killable).
8686
unkillable: int,
87-
// nesting level counter for task::atomically calls (0 == can yield).
87+
// nesting level counter for unstable::atomically calls (0 == can yield).
8888
wont_sleep: int,
8989
// A "spare" handle to the kill flag inside the kill handle. Used during
9090
// blocking/waking as an optimization to avoid two xadds on the refcount.

src/libstd/rt/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,14 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
316316
// Just put an unpinned task onto one of the default schedulers.
317317
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, main);
318318
main_task.death.on_exit = Some(on_exit);
319+
main_task.name = Some(~"main");
319320
scheds[0].enqueue_task(main_task);
320321
}
321322
Some(ref mut main_sched) => {
322323
let home = Sched(main_sched.make_handle());
323324
let mut main_task = ~Task::new_root_homed(&mut scheds[0].stack_pool, home, main);
324325
main_task.death.on_exit = Some(on_exit);
326+
main_task.name = Some(~"main");
325327
main_sched.enqueue_task(main_task);
326328
}
327329
};

src/libstd/rt/task.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ pub struct Task {
4040
taskgroup: Option<Taskgroup>,
4141
death: Death,
4242
destroyed: bool,
43-
coroutine: Option<~Coroutine>
43+
coroutine: Option<~Coroutine>,
44+
// FIXME(#6874/#7599) use StringRef to save on allocations
45+
name: Option<~str>,
4446
}
4547

4648
pub struct Coroutine {
@@ -90,7 +92,8 @@ impl Task {
9092
taskgroup: None,
9193
death: Death::new(),
9294
destroyed: false,
93-
coroutine: Some(~Coroutine::new(stack_pool, start))
95+
coroutine: Some(~Coroutine::new(stack_pool, start)),
96+
name: None,
9497
}
9598
}
9699

@@ -109,7 +112,8 @@ impl Task {
109112
// FIXME(#7544) make watching optional
110113
death: self.death.new_child(),
111114
destroyed: false,
112-
coroutine: Some(~Coroutine::new(stack_pool, start))
115+
coroutine: Some(~Coroutine::new(stack_pool, start)),
116+
name: None,
113117
}
114118
}
115119

src/libstd/sys.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -137,12 +137,13 @@ impl FailWithCause for &'static str {
137137

138138
// FIXME #4427: Temporary until rt::rt_fail_ goes away
139139
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
140-
use cell::Cell;
141140
use either::Left;
141+
use option::{Some, None};
142142
use rt::{context, OldTaskContext, TaskContext};
143143
use rt::task::Task;
144144
use rt::local::Local;
145145
use rt::logging::Logger;
146+
use str::Str;
146147

147148
let context = context();
148149
match context {
@@ -159,20 +160,26 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
159160
let msg = str::raw::from_c_str(msg);
160161
let file = str::raw::from_c_str(file);
161162

162-
let outmsg = fmt!("task failed at '%s', %s:%i",
163-
msg, file, line as int);
164-
165163
// XXX: Logging doesn't work correctly in non-task context because it
166164
// invokes the local heap
167165
if context == TaskContext {
168166
// XXX: Logging doesn't work here - the check to call the log
169167
// function never passes - so calling the log function directly.
170-
let outmsg = Cell::new(outmsg);
171168
do Local::borrow::<Task, ()> |task| {
172-
task.logger.log(Left(outmsg.take()));
169+
let msg = match task.name {
170+
Some(ref name) =>
171+
fmt!("task '%s' failed at '%s', %s:%i",
172+
name.as_slice(), msg, file, line as int),
173+
None =>
174+
fmt!("task <unnamed> failed at '%s', %s:%i",
175+
msg, file, line as int)
176+
};
177+
178+
task.logger.log(Left(msg));
173179
}
174180
} else {
175-
rterrln!("%s", outmsg);
181+
rterrln!("failed in non-task context at '%s', %s:%i",
182+
msg, file, line as int);
176183
}
177184

178185
gc::cleanup_stack_for_failure();

src/libstd/task/mod.rs

+57-55
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ pub struct SchedOpts {
120120
*
121121
* * notify_chan - Enable lifecycle notifications on the given channel
122122
*
123+
* * name - A name for the task-to-be, for identification in failure messages.
124+
*
123125
* * sched - Specify the configuration of a new scheduler to create the task
124126
* in
125127
*
@@ -139,6 +141,7 @@ pub struct TaskOpts {
139141
watched: bool,
140142
indestructible: bool,
141143
notify_chan: Option<Chan<TaskResult>>,
144+
name: Option<~str>,
142145
sched: SchedOpts
143146
}
144147

@@ -185,23 +188,23 @@ impl TaskBuilder {
185188
self.consumed = true;
186189
let gen_body = self.gen_body.take();
187190
let notify_chan = self.opts.notify_chan.take();
191+
let name = self.opts.name.take();
188192
TaskBuilder {
189193
opts: TaskOpts {
190194
linked: self.opts.linked,
191195
supervised: self.opts.supervised,
192196
watched: self.opts.watched,
193197
indestructible: self.opts.indestructible,
194198
notify_chan: notify_chan,
199+
name: name,
195200
sched: self.opts.sched
196201
},
197202
gen_body: gen_body,
198203
can_not_copy: None,
199204
consumed: false
200205
}
201206
}
202-
}
203207

204-
impl TaskBuilder {
205208
/// Decouple the child task's failure from the parent's. If either fails,
206209
/// the other will not be killed.
207210
pub fn unlinked(&mut self) {
@@ -281,6 +284,12 @@ impl TaskBuilder {
281284
self.opts.notify_chan = Some(notify_pipe_ch);
282285
}
283286

287+
/// Name the task-to-be. Currently the name is used for identification
288+
/// only in failure messages.
289+
pub fn name(&mut self, name: ~str) {
290+
self.opts.name = Some(name);
291+
}
292+
284293
/// Configure a custom scheduler mode for the task.
285294
pub fn sched_mode(&mut self, mode: SchedMode) {
286295
self.opts.sched.mode = mode;
@@ -333,13 +342,15 @@ impl TaskBuilder {
333342
pub fn spawn(&mut self, f: ~fn()) {
334343
let gen_body = self.gen_body.take();
335344
let notify_chan = self.opts.notify_chan.take();
345+
let name = self.opts.name.take();
336346
let x = self.consume();
337347
let opts = TaskOpts {
338348
linked: x.opts.linked,
339349
supervised: x.opts.supervised,
340350
watched: x.opts.watched,
341351
indestructible: x.opts.indestructible,
342352
notify_chan: notify_chan,
353+
name: name,
343354
sched: x.opts.sched
344355
};
345356
let f = match gen_body {
@@ -408,6 +419,7 @@ pub fn default_task_opts() -> TaskOpts {
408419
watched: true,
409420
indestructible: false,
410421
notify_chan: None,
422+
name: None,
411423
sched: SchedOpts {
412424
mode: DefaultScheduler,
413425
}
@@ -507,6 +519,21 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
507519

508520
/* Lifecycle functions */
509521

522+
/// Read the name of the current task.
523+
pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
524+
use rt::task::Task;
525+
526+
match context() {
527+
TaskContext => do Local::borrow::<Task, U> |task| {
528+
match task.name {
529+
Some(ref name) => blk(Some(name.as_slice())),
530+
None => blk(None)
531+
}
532+
},
533+
_ => fail!("no task name exists in %?", context()),
534+
}
535+
}
536+
510537
pub fn yield() {
511538
//! Yield control to the task scheduler
512539
@@ -628,44 +655,6 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
628655
}
629656
}
630657

631-
/**
632-
* A stronger version of unkillable that also inhibits scheduling operations.
633-
* For use with exclusive Arcs, which use pthread mutexes directly.
634-
*/
635-
pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
636-
use rt::task::Task;
637-
638-
match context() {
639-
OldTaskContext => {
640-
let t = rt::rust_get_task();
641-
do (|| {
642-
rt::rust_task_inhibit_kill(t);
643-
rt::rust_task_inhibit_yield(t);
644-
f()
645-
}).finally {
646-
rt::rust_task_allow_yield(t);
647-
rt::rust_task_allow_kill(t);
648-
}
649-
}
650-
TaskContext => {
651-
let t = Local::unsafe_borrow::<Task>();
652-
do (|| {
653-
// It's important to inhibit kill after inhibiting yield, because
654-
// inhibit-kill might fail if we were already killed, and the
655-
// inhibit-yield must happen to match the finally's allow-yield.
656-
(*t).death.inhibit_yield();
657-
(*t).death.inhibit_kill((*t).unwinder.unwinding);
658-
f()
659-
}).finally {
660-
(*t).death.allow_kill((*t).unwinder.unwinding);
661-
(*t).death.allow_yield();
662-
}
663-
}
664-
// FIXME(#3095): As in unkillable().
665-
_ => f()
666-
}
667-
}
668-
669658
#[test] #[should_fail] #[ignore(cfg(windows))]
670659
fn test_cant_dup_task_builder() {
671660
let mut builder = task();
@@ -805,6 +794,34 @@ fn test_spawn_linked_sup_propagate_sibling() {
805794
fail!();
806795
}
807796

797+
#[test]
798+
fn test_unnamed_task() {
799+
use rt::test::run_in_newsched_task;
800+
801+
do run_in_newsched_task {
802+
do spawn {
803+
do with_task_name |name| {
804+
assert!(name.is_none());
805+
}
806+
}
807+
}
808+
}
809+
810+
#[test]
811+
fn test_named_task() {
812+
use rt::test::run_in_newsched_task;
813+
814+
do run_in_newsched_task {
815+
let mut t = task();
816+
t.name(~"ada lovelace");
817+
do t.spawn {
818+
do with_task_name |name| {
819+
assert!(name.get() == "ada lovelace");
820+
}
821+
}
822+
}
823+
}
824+
808825
#[test]
809826
fn test_run_basic() {
810827
let (po, ch) = stream::<()>();
@@ -1122,21 +1139,6 @@ fn test_unkillable_nested() {
11221139
po.recv();
11231140
}
11241141

1125-
#[test] #[should_fail] #[ignore(cfg(windows))]
1126-
fn test_atomically() {
1127-
unsafe { do atomically { yield(); } }
1128-
}
1129-
1130-
#[test]
1131-
fn test_atomically2() {
1132-
unsafe { do atomically { } } yield(); // shouldn't fail
1133-
}
1134-
1135-
#[test] #[should_fail] #[ignore(cfg(windows))]
1136-
fn test_atomically_nested() {
1137-
unsafe { do atomically { do atomically { } yield(); } }
1138-
}
1139-
11401142
#[test]
11411143
fn test_child_doesnt_ref_parent() {
11421144
// If the child refcounts the parent task, this will stack overflow when

src/libstd/task/spawn.rs

+2
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,8 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
725725
task.death.on_exit = Some(on_exit);
726726
}
727727

728+
task.name = opts.name.take();
729+
728730
rtdebug!("spawn about to take scheduler");
729731

730732
let sched = Local::take::<Scheduler>();

src/libstd/unstable/dynamic_lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ mod dl {
105105
use path;
106106
use ptr;
107107
use str;
108-
use task;
108+
use unstable::sync::atomically;
109109
use result::*;
110110

111111
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
@@ -120,7 +120,7 @@ mod dl {
120120

121121
pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
122122
unsafe {
123-
do task::atomically {
123+
do atomically {
124124
let _old_error = dlerror();
125125

126126
let result = f();
@@ -164,7 +164,7 @@ mod dl {
164164
use libc;
165165
use path;
166166
use ptr;
167-
use task;
167+
use unstable::sync::atomically;
168168
use result::*;
169169

170170
pub unsafe fn open_external(filename: &path::Path) -> *libc::c_void {
@@ -181,7 +181,7 @@ mod dl {
181181

182182
pub fn check_for_errors_in<T>(f: &fn()->T) -> Result<T, ~str> {
183183
unsafe {
184-
do task::atomically {
184+
do atomically {
185185
SetLastError(0);
186186

187187
let result = f();

src/libstd/unstable/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,15 @@ fn test_run_in_bare_thread_exchange() {
8585
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
8686
use os;
8787
use os::change_dir;
88-
use task;
88+
use unstable::sync::atomically;
8989
use unstable::finally::Finally;
9090

9191
unsafe {
9292
// This is really sketchy. Using a pthread mutex so descheduling
9393
// in the `action` callback can cause deadlock. Doing it in
9494
// `task::atomically` to try to avoid that, but ... I don't know
9595
// this is all bogus.
96-
return do task::atomically {
96+
return do atomically {
9797
rust_take_change_dir_lock();
9898

9999
do (||{

0 commit comments

Comments
 (0)