// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Native threads
+//! Native threads.
//!
//! ## The threading model
//!
use cell::UnsafeCell;
use fmt;
use io;
+use str;
+use ffi::{CStr, CString};
use sync::{Mutex, Condvar, Arc};
use sys::thread as imp;
use sys_common::thread_info;
let their_packet = my_packet.clone();
let main = move || {
- if let Some(name) = their_thread.name() {
+ if let Some(name) = their_thread.cname() {
imp::Thread::set_name(name);
}
unsafe {
Ok(JoinHandle(JoinInner {
native: unsafe {
- Some(try!(imp::Thread::new(stack_size, Box::new(main))))
+ Some(imp::Thread::new(stack_size, Box::new(main))?)
},
thread: my_thread,
packet: Packet(my_packet),
unwind::panicking()
}
-/// Invokes a closure, capturing the cause of panic if one occurs.
-///
-/// This function will return `Ok` with the closure's result if the closure
-/// does not panic, and will return `Err(cause)` if the closure panics. The
-/// `cause` returned is the object with which panic was originally invoked.
-///
-/// It is currently undefined behavior to unwind from Rust code into foreign
-/// code, so this function is particularly useful when Rust is called from
-/// another language (normally C). This can run arbitrary Rust code, capturing a
-/// panic and allowing a graceful handling of the error.
-///
-/// It is **not** recommended to use this function for a general try/catch
-/// mechanism. The `Result` type is more appropriate to use for functions that
-/// can fail on a regular basis.
-///
-/// The closure provided is required to adhere to the `'static` bound to ensure
-/// that it cannot reference data in the parent stack frame, mitigating problems
-/// with exception safety. Furthermore, a `Send` bound is also required,
-/// providing the same safety guarantees as `thread::spawn` (ensuring the
-/// closure is properly isolated from the parent).
-#[unstable(feature = "catch_panic", reason = "recent API addition",
- issue = "27719")]
-#[rustc_deprecated(since = "1.6.0", reason = "renamed to std::panic::recover")]
-pub fn catch_panic<F, R>(f: F) -> Result<R>
- where F: FnOnce() -> R + Send + 'static
-{
- let mut result = None;
- unsafe {
- let result = &mut result;
- try!(unwind::try(move || *result = Some(f())))
- }
- Ok(result.unwrap())
-}
-
/// Puts the current thread to sleep for the specified amount of time.
///
/// The thread may sleep longer than the duration specified due to scheduling
/// The internal representation of a `Thread` handle
struct Inner {
- name: Option<String>,
+ name: Option<CString>, // Guaranteed to be UTF-8
lock: Mutex<bool>, // true when there is a buffered unpark
cvar: Condvar,
}
impl Thread {
// Used only internally to construct a thread object without spawning
fn new(name: Option<String>) -> Thread {
+ let cname = name.map(|n| CString::new(n).unwrap_or_else(|_| {
+ panic!("thread name may not contain interior null bytes")
+ }));
Thread {
inner: Arc::new(Inner {
- name: name,
+ name: cname,
lock: Mutex::new(false),
cvar: Condvar::new(),
})
/// Gets the thread's name.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn name(&self) -> Option<&str> {
+ self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) } )
+ }
+
+ fn cname(&self) -> Option<&CStr> {
self.inner.name.as_ref().map(|s| &**s)
}
}
}).unwrap().join().unwrap();
}
+ #[test]
+ #[should_panic]
+ fn test_invalid_named_thread() {
+ let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {});
+ }
+
#[test]
fn test_run_basic() {
let (tx, rx) = channel();