Skip to content

Commit

Permalink
Give tasks useful names. #2891
Browse files Browse the repository at this point in the history
  • Loading branch information
bblum committed Jul 31, 2013
1 parent 389aba0 commit 2e6dc16
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,14 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
// Just put an unpinned task onto one of the default schedulers.
let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool, main);
main_task.death.on_exit = Some(on_exit);
main_task.name = Some(~"main");
scheds[0].enqueue_task(main_task);
}
Some(ref mut main_sched) => {
let home = Sched(main_sched.make_handle());
let mut main_task = ~Task::new_root_homed(&mut scheds[0].stack_pool, home, main);
main_task.death.on_exit = Some(on_exit);
main_task.name = Some(~"main");
main_sched.enqueue_task(main_task);
}
};
Expand Down
10 changes: 7 additions & 3 deletions src/libstd/rt/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ pub struct Task {
taskgroup: Option<Taskgroup>,
death: Death,
destroyed: bool,
coroutine: Option<~Coroutine>
coroutine: Option<~Coroutine>,
// FIXME(#6874/#7599) use StringRef to save on allocations
name: Option<~str>,
}

pub struct Coroutine {
Expand Down Expand Up @@ -90,7 +92,8 @@ impl Task {
taskgroup: None,
death: Death::new(),
destroyed: false,
coroutine: Some(~Coroutine::new(stack_pool, start))
coroutine: Some(~Coroutine::new(stack_pool, start)),
name: None,
}
}

Expand All @@ -109,7 +112,8 @@ impl Task {
// FIXME(#7544) make watching optional
death: self.death.new_child(),
destroyed: false,
coroutine: Some(~Coroutine::new(stack_pool, start))
coroutine: Some(~Coroutine::new(stack_pool, start)),
name: None,
}
}

Expand Down
21 changes: 14 additions & 7 deletions src/libstd/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,13 @@ impl FailWithCause for &'static str {

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

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

let outmsg = fmt!("task failed at '%s', %s:%i",
msg, file, line as int);

// XXX: Logging doesn't work correctly in non-task context because it
// invokes the local heap
if context == TaskContext {
// XXX: Logging doesn't work here - the check to call the log
// function never passes - so calling the log function directly.
let outmsg = Cell::new(outmsg);
do Local::borrow::<Task, ()> |task| {
task.logger.log(Left(outmsg.take()));
let msg = match task.name {
Some(ref name) =>
fmt!("task '%s' failed at '%s', %s:%i",
name.as_slice(), msg, file, line as int),
None =>
fmt!("task <unnamed> failed at '%s', %s:%i",
msg, file, line as int)
};

task.logger.log(Left(msg));
}
} else {
rterrln!("%s", outmsg);
rterrln!("failed in non-task context at '%s', %s:%i",
msg, file, line as int);
}

gc::cleanup_stack_for_failure();
Expand Down
59 changes: 57 additions & 2 deletions src/libstd/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ pub struct SchedOpts {
*
* * notify_chan - Enable lifecycle notifications on the given channel
*
* * name - A name for the task-to-be, for identification in failure messages.
*
* * sched - Specify the configuration of a new scheduler to create the task
* in
*
Expand All @@ -139,6 +141,7 @@ pub struct TaskOpts {
watched: bool,
indestructible: bool,
notify_chan: Option<Chan<TaskResult>>,
name: Option<~str>,
sched: SchedOpts
}

Expand Down Expand Up @@ -185,23 +188,23 @@ impl TaskBuilder {
self.consumed = true;
let gen_body = self.gen_body.take();
let notify_chan = self.opts.notify_chan.take();
let name = self.opts.name.take();
TaskBuilder {
opts: TaskOpts {
linked: self.opts.linked,
supervised: self.opts.supervised,
watched: self.opts.watched,
indestructible: self.opts.indestructible,
notify_chan: notify_chan,
name: name,
sched: self.opts.sched
},
gen_body: gen_body,
can_not_copy: None,
consumed: false
}
}
}

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

/// Name the task-to-be. Currently the name is used for identification
/// only in failure messages.
pub fn name(&mut self, name: ~str) {
self.opts.name = Some(name);
}

/// Configure a custom scheduler mode for the task.
pub fn sched_mode(&mut self, mode: SchedMode) {
self.opts.sched.mode = mode;
Expand Down Expand Up @@ -333,13 +342,15 @@ impl TaskBuilder {
pub fn spawn(&mut self, f: ~fn()) {
let gen_body = self.gen_body.take();
let notify_chan = self.opts.notify_chan.take();
let name = self.opts.name.take();
let x = self.consume();
let opts = TaskOpts {
linked: x.opts.linked,
supervised: x.opts.supervised,
watched: x.opts.watched,
indestructible: x.opts.indestructible,
notify_chan: notify_chan,
name: name,
sched: x.opts.sched
};
let f = match gen_body {
Expand Down Expand Up @@ -408,6 +419,7 @@ pub fn default_task_opts() -> TaskOpts {
watched: true,
indestructible: false,
notify_chan: None,
name: None,
sched: SchedOpts {
mode: DefaultScheduler,
}
Expand Down Expand Up @@ -507,6 +519,21 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {

/* Lifecycle functions */

/// Read the name of the current task.
pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
use rt::task::Task;

match context() {
TaskContext => do Local::borrow::<Task, U> |task| {
match task.name {
Some(ref name) => blk(Some(name.as_slice())),
None => blk(None)
}
},
_ => fail!("no task name exists in %?", context()),
}
}

pub fn yield() {
//! Yield control to the task scheduler

Expand Down Expand Up @@ -805,6 +832,34 @@ fn test_spawn_linked_sup_propagate_sibling() {
fail!();
}

#[test]
fn test_unnamed_task() {
use rt::test::run_in_newsched_task;

do run_in_newsched_task {
do spawn {
do with_task_name |name| {
assert!(name.is_none());
}
}
}
}

#[test]
fn test_named_task() {
use rt::test::run_in_newsched_task;

do run_in_newsched_task {
let mut t = task();
t.name(~"ada lovelace");
do t.spawn {
do with_task_name |name| {
assert!(name.get() == "ada lovelace");
}
}
}
}

#[test]
fn test_run_basic() {
let (po, ch) = stream::<()>();
Expand Down
2 changes: 2 additions & 0 deletions src/libstd/task/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,8 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
task.death.on_exit = Some(on_exit);
}

task.name = opts.name.take();

rtdebug!("spawn about to take scheduler");

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

0 comments on commit 2e6dc16

Please sign in to comment.