]> git.lizzy.rs Git - rust.git/blob - src/libstd/failure.rs
Register new snapshots
[rust.git] / src / libstd / failure.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use alloc::owned::Box;
12 use any::{Any, AnyRefExt};
13 use fmt;
14 use io::{Writer, IoResult};
15 use kinds::Send;
16 use option::{Some, None};
17 use result::Ok;
18 use rt::backtrace;
19 use rt::{Stderr, Stdio};
20 use rustrt::local::Local;
21 use rustrt::task::Task;
22 use str::Str;
23 use string::String;
24
25 // Defined in this module instead of io::stdio so that the unwinding
26 local_data_key!(pub local_stderr: Box<Writer + Send>)
27
28 impl Writer for Stdio {
29     fn write(&mut self, bytes: &[u8]) -> IoResult<()> {
30         fn fmt_write<F: fmt::FormatWriter>(f: &mut F, bytes: &[u8]) {
31             let _ = f.write(bytes);
32         }
33         fmt_write(self, bytes);
34         Ok(())
35     }
36 }
37
38 pub fn on_fail(obj: &Any + Send, file: &'static str, line: uint) {
39     let msg = match obj.as_ref::<&'static str>() {
40         Some(s) => *s,
41         None => match obj.as_ref::<String>() {
42             Some(s) => s.as_slice(),
43             None => "Box<Any>",
44         }
45     };
46     let mut err = Stderr;
47
48     // It is assumed that all reasonable rust code will have a local task at
49     // all times. This means that this `exists` will return true almost all of
50     // the time. There are border cases, however, when the runtime has
51     // *almost* set up the local task, but hasn't quite gotten there yet. In
52     // order to get some better diagnostics, we print on failure and
53     // immediately abort the whole process if there is no local task
54     // available.
55     if !Local::exists(None::<Task>) {
56         let _ = writeln!(&mut err, "failed at '{}', {}:{}", msg, file, line);
57         if backtrace::log_enabled() {
58             let _ = backtrace::write(&mut err);
59         } else {
60             let _ = writeln!(&mut err, "run with `RUST_BACKTRACE=1` to \
61                                         see a backtrace");
62         }
63         return
64     }
65
66     // Peel the name out of local task so we can print it. We've got to be sure
67     // that the local task is in TLS while we're printing as I/O may occur.
68     let (name, unwinding) = {
69         let mut t = Local::borrow(None::<Task>);
70         (t.name.take(), t.unwinder.unwinding())
71     };
72     {
73         let n = name.as_ref().map(|n| n.as_slice()).unwrap_or("<unnamed>");
74
75         match local_stderr.replace(None) {
76             Some(mut stderr) => {
77                 // FIXME: what to do when the task printing fails?
78                 let _ = writeln!(stderr,
79                                  "task '{}' failed at '{}', {}:{}\n",
80                                  n, msg, file, line);
81                 if backtrace::log_enabled() {
82                     let _ = backtrace::write(stderr);
83                 }
84                 local_stderr.replace(Some(stderr));
85             }
86             None => {
87                 let _ = writeln!(&mut err, "task '{}' failed at '{}', {}:{}",
88                                  n, msg, file, line);
89                 if backtrace::log_enabled() {
90                     let _ = backtrace::write(&mut err);
91                 }
92             }
93         }
94
95         // If this is a double failure, make sure that we printed a backtrace
96         // for this failure.
97         if unwinding && !backtrace::log_enabled() {
98             let _ = backtrace::write(&mut err);
99         }
100     }
101     Local::borrow(None::<Task>).name = name;
102 }