2013-06-18 05:17:51 +00:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
2014-11-24 03:21:17 +00:00
|
|
|
//
|
|
|
|
// ignore-lexer-test FIXME #15677
|
|
|
|
|
|
|
|
use core::prelude::*;
|
2013-06-18 05:17:51 +00:00
|
|
|
|
2014-11-24 03:21:17 +00:00
|
|
|
use core::cmp;
|
|
|
|
use core::fmt;
|
|
|
|
use core::intrinsics;
|
|
|
|
use core::slice;
|
|
|
|
use core::str;
|
|
|
|
|
|
|
|
use libc::{mod, uintptr_t};
|
2013-06-24 01:22:57 +00:00
|
|
|
use os;
|
2014-11-15 04:52:00 +00:00
|
|
|
use str::{FromStr, from_str, Str};
|
2014-08-04 22:42:36 +00:00
|
|
|
use sync::atomic;
|
2013-08-17 06:14:55 +00:00
|
|
|
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-04 02:11:49 +00:00
|
|
|
/// Dynamically inquire about whether we're running under V.
|
|
|
|
/// You should usually not use this unless your test definitely
|
|
|
|
/// can't run correctly un-altered. Valgrind is there to help
|
|
|
|
/// you notice weirdness in normal, un-doctored code paths!
|
|
|
|
pub fn running_on_valgrind() -> bool {
|
|
|
|
extern {
|
|
|
|
fn rust_running_on_valgrind() -> uintptr_t;
|
|
|
|
}
|
|
|
|
unsafe { rust_running_on_valgrind() != 0 }
|
|
|
|
}
|
|
|
|
|
2013-10-09 17:34:27 +00:00
|
|
|
/// Valgrind has a fixed-sized array (size around 2000) of segment descriptors
|
|
|
|
/// wired into it; this is a hard limit and requires rebuilding valgrind if you
|
|
|
|
/// want to go beyond it. Normally this is not a problem, but in some tests, we
|
|
|
|
/// produce a lot of threads casually. Making lots of threads alone might not
|
|
|
|
/// be a problem _either_, except on OSX, the segments produced for new threads
|
|
|
|
/// _take a while_ to get reclaimed by the OS. Combined with the fact that libuv
|
|
|
|
/// schedulers fork off a separate thread for polling fsevents on OSX, we get a
|
|
|
|
/// perfect storm of creating "too many mappings" for valgrind to handle when
|
|
|
|
/// running certain stress tests in the runtime.
|
2013-08-09 23:30:44 +00:00
|
|
|
pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
|
2013-10-09 17:34:27 +00:00
|
|
|
(cfg!(target_os="macos")) && running_on_valgrind()
|
2013-08-09 23:30:44 +00:00
|
|
|
}
|
|
|
|
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-04 02:11:49 +00:00
|
|
|
pub fn min_stack() -> uint {
|
2014-10-11 04:59:10 +00:00
|
|
|
static MIN: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT;
|
|
|
|
match MIN.load(atomic::SeqCst) {
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-04 02:11:49 +00:00
|
|
|
0 => {}
|
|
|
|
n => return n - 1,
|
|
|
|
}
|
|
|
|
let amt = os::getenv("RUST_MIN_STACK").and_then(|s| from_str(s.as_slice()));
|
|
|
|
let amt = amt.unwrap_or(2 * 1024 * 1024);
|
|
|
|
// 0 is our sentinel value, so ensure that we'll never see 0 after
|
|
|
|
// initialization has run
|
2014-10-11 04:59:10 +00:00
|
|
|
MIN.store(amt + 1, atomic::SeqCst);
|
std: Extract librustrt out of libstd
As part of the libstd facade efforts, this commit extracts the runtime interface
out of the standard library into a standalone crate, librustrt. This crate will
provide the following services:
* Definition of the rtio interface
* Definition of the Runtime interface
* Implementation of the Task structure
* Implementation of task-local-data
* Implementation of task failure via unwinding via libunwind
* Implementation of runtime initialization and shutdown
* Implementation of thread-local-storage for the local rust Task
Notably, this crate avoids the following services:
* Thread creation and destruction. The crate does not require the knowledge of
an OS threading system, and as a result it seemed best to leave out the
`rt::thread` module from librustrt. The librustrt module does depend on
mutexes, however.
* Implementation of backtraces. There is no inherent requirement for the runtime
to be able to generate backtraces. As will be discussed later, this
functionality continues to live in libstd rather than librustrt.
As usual, a number of architectural changes were required to make this crate
possible. Users of "stable" functionality will not be impacted by this change,
but users of the `std::rt` module will likely note the changes. A list of
architectural changes made is:
* The stdout/stderr handles no longer live directly inside of the `Task`
structure. This is a consequence of librustrt not knowing about `std::io`.
These two handles are now stored inside of task-local-data.
The handles were originally stored inside of the `Task` for perf reasons, and
TLD is not currently as fast as it could be. For comparison, 100k prints goes
from 59ms to 68ms (a 15% slowdown). This appeared to me to be an acceptable
perf loss for the successful extraction of a librustrt crate.
* The `rtio` module was forced to duplicate more functionality of `std::io`. As
the module no longer depends on `std::io`, `rtio` now defines structures such
as socket addresses, addrinfo fiddly bits, etc. The primary change made was
that `rtio` now defines its own `IoError` type. This type is distinct from
`std::io::IoError` in that it does not have an enum for what error occurred,
but rather a platform-specific error code.
The native and green libraries will be updated in later commits for this
change, and the bulk of this effort was put behind updating the two libraries
for this change (with `rtio`).
* Printing a message on task failure (along with the backtrace) continues to
live in libstd, not in librustrt. This is a consequence of the above decision
to move the stdout/stderr handles to TLD rather than inside the `Task` itself.
The unwinding API now supports registration of global callback functions which
will be invoked when a task fails, allowing for libstd to register a function
to print a message and a backtrace.
The API for registering a callback is experimental and unsafe, as the
ramifications of running code on unwinding is pretty hairy.
* The `std::unstable::mutex` module has moved to `std::rt::mutex`.
* The `std::unstable::sync` module has been moved to `std::rt::exclusive` and
the type has been rewritten to not internally have an Arc and to have an RAII
guard structure when locking. Old code should stop using `Exclusive` in favor
of the primitives in `libsync`, but if necessary, old code should port to
`Arc<Exclusive<T>>`.
* The local heap has been stripped down to have fewer debugging options. None of
these were tested, and none of these have been used in a very long time.
[breaking-change]
2014-06-04 02:11:49 +00:00
|
|
|
return amt;
|
|
|
|
}
|
|
|
|
|
2013-06-24 01:22:57 +00:00
|
|
|
/// Get's the number of scheduler threads requested by the environment
|
|
|
|
/// either `RUST_THREADS` or `num_cpus`.
|
|
|
|
pub fn default_sched_threads() -> uint {
|
|
|
|
match os::getenv("RUST_THREADS") {
|
2013-08-29 10:57:37 +00:00
|
|
|
Some(nstr) => {
|
2014-05-16 17:45:16 +00:00
|
|
|
let opt_n: Option<uint> = FromStr::from_str(nstr.as_slice());
|
2013-08-29 10:57:37 +00:00
|
|
|
match opt_n {
|
|
|
|
Some(n) if n > 0 => n,
|
2014-10-09 19:17:22 +00:00
|
|
|
_ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
|
2013-08-29 10:57:37 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-09 23:30:44 +00:00
|
|
|
None => {
|
|
|
|
if limit_thread_creation_due_to_osx_and_valgrind() {
|
|
|
|
1
|
|
|
|
} else {
|
2014-06-16 20:36:07 +00:00
|
|
|
os::num_cpus()
|
2013-08-09 23:30:44 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-24 01:22:57 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-24 03:21:17 +00:00
|
|
|
|
|
|
|
// Indicates whether we should perform expensive sanity checks, including rtassert!
|
|
|
|
//
|
|
|
|
// FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
|
|
|
|
// etc.
|
|
|
|
pub const ENFORCE_SANITY: bool = true || !cfg!(rtopt) || cfg!(rtdebug) ||
|
|
|
|
cfg!(rtassert);
|
|
|
|
|
2014-12-14 08:05:32 +00:00
|
|
|
#[allow(missing_copy_implementations)]
|
2014-11-24 03:21:17 +00:00
|
|
|
pub struct Stdio(libc::c_int);
|
|
|
|
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO);
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO);
|
|
|
|
|
|
|
|
impl fmt::FormatWriter for Stdio {
|
|
|
|
fn write(&mut self, data: &[u8]) -> fmt::Result {
|
|
|
|
#[cfg(unix)]
|
|
|
|
type WriteLen = libc::size_t;
|
|
|
|
#[cfg(windows)]
|
|
|
|
type WriteLen = libc::c_uint;
|
|
|
|
unsafe {
|
|
|
|
let Stdio(fd) = *self;
|
|
|
|
libc::write(fd,
|
|
|
|
data.as_ptr() as *const libc::c_void,
|
|
|
|
data.len() as WriteLen);
|
|
|
|
}
|
|
|
|
Ok(()) // yes, we're lying
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dumb_print(args: &fmt::Arguments) {
|
|
|
|
use fmt::FormatWriter;
|
|
|
|
let mut w = Stderr;
|
|
|
|
let _ = w.write_fmt(args);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn abort(args: &fmt::Arguments) -> ! {
|
|
|
|
use fmt::FormatWriter;
|
|
|
|
|
|
|
|
struct BufWriter<'a> {
|
|
|
|
buf: &'a mut [u8],
|
|
|
|
pos: uint,
|
|
|
|
}
|
|
|
|
impl<'a> FormatWriter for BufWriter<'a> {
|
|
|
|
fn write(&mut self, bytes: &[u8]) -> fmt::Result {
|
|
|
|
let left = self.buf[mut self.pos..];
|
|
|
|
let to_write = bytes[..cmp::min(bytes.len(), left.len())];
|
|
|
|
slice::bytes::copy_memory(left, to_write);
|
|
|
|
self.pos += to_write.len();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the arguments into a stack-allocated string
|
|
|
|
let mut msg = [0u8, ..512];
|
|
|
|
let mut w = BufWriter { buf: &mut msg, pos: 0 };
|
|
|
|
let _ = write!(&mut w, "{}", args);
|
|
|
|
let msg = str::from_utf8(w.buf[mut ..w.pos]).unwrap_or("aborted");
|
|
|
|
let msg = if msg.is_empty() {"aborted"} else {msg};
|
|
|
|
|
|
|
|
// Give some context to the message
|
|
|
|
let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
|
|
|
|
let quote = match hash % 10 {
|
|
|
|
0 => "
|
|
|
|
It was from the artists and poets that the pertinent answers came, and I
|
|
|
|
know that panic would have broken loose had they been able to compare notes.
|
|
|
|
As it was, lacking their original letters, I half suspected the compiler of
|
|
|
|
having asked leading questions, or of having edited the correspondence in
|
|
|
|
corroboration of what he had latently resolved to see.",
|
|
|
|
1 => "
|
|
|
|
There are not many persons who know what wonders are opened to them in the
|
|
|
|
stories and visions of their youth; for when as children we listen and dream,
|
|
|
|
we think but half-formed thoughts, and when as men we try to remember, we are
|
|
|
|
dulled and prosaic with the poison of life. But some of us awake in the night
|
|
|
|
with strange phantasms of enchanted hills and gardens, of fountains that sing
|
|
|
|
in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
|
|
|
|
down to sleeping cities of bronze and stone, and of shadowy companies of heroes
|
|
|
|
that ride caparisoned white horses along the edges of thick forests; and then
|
|
|
|
we know that we have looked back through the ivory gates into that world of
|
|
|
|
wonder which was ours before we were wise and unhappy.",
|
|
|
|
2 => "
|
|
|
|
Instead of the poems I had hoped for, there came only a shuddering blackness
|
|
|
|
and ineffable loneliness; and I saw at last a fearful truth which no one had
|
|
|
|
ever dared to breathe before — the unwhisperable secret of secrets — The fact
|
|
|
|
that this city of stone and stridor is not a sentient perpetuation of Old New
|
|
|
|
York as London is of Old London and Paris of Old Paris, but that it is in fact
|
|
|
|
quite dead, its sprawling body imperfectly embalmed and infested with queer
|
|
|
|
animate things which have nothing to do with it as it was in life.",
|
|
|
|
3 => "
|
|
|
|
The ocean ate the last of the land and poured into the smoking gulf, thereby
|
|
|
|
giving up all it had ever conquered. From the new-flooded lands it flowed
|
|
|
|
again, uncovering death and decay; and from its ancient and immemorial bed it
|
|
|
|
trickled loathsomely, uncovering nighted secrets of the years when Time was
|
|
|
|
young and the gods unborn. Above the waves rose weedy remembered spires. The
|
|
|
|
moon laid pale lilies of light on dead London, and Paris stood up from its damp
|
|
|
|
grave to be sanctified with star-dust. Then rose spires and monoliths that were
|
|
|
|
weedy but not remembered; terrible spires and monoliths of lands that men never
|
|
|
|
knew were lands...",
|
|
|
|
4 => "
|
|
|
|
There was a night when winds from unknown spaces whirled us irresistibly into
|
|
|
|
limitless vacuum beyond all thought and entity. Perceptions of the most
|
|
|
|
maddeningly untransmissible sort thronged upon us; perceptions of infinity
|
|
|
|
which at the time convulsed us with joy, yet which are now partly lost to my
|
|
|
|
memory and partly incapable of presentation to others.",
|
|
|
|
_ => "You've met with a terrible fate, haven't you?"
|
|
|
|
};
|
|
|
|
rterrln!("{}", "");
|
|
|
|
rterrln!("{}", quote);
|
|
|
|
rterrln!("{}", "");
|
|
|
|
rterrln!("fatal runtime error: {}", msg);
|
|
|
|
unsafe { intrinsics::abort(); }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub unsafe fn report_overflow() {
|
2014-12-07 02:34:37 +00:00
|
|
|
use thread::Thread;
|
2014-11-24 03:21:17 +00:00
|
|
|
|
|
|
|
// See the message below for why this is not emitted to the
|
|
|
|
// ^ Where did the message below go?
|
|
|
|
// task's logger. This has the additional conundrum of the
|
|
|
|
// logger may not be initialized just yet, meaning that an FFI
|
|
|
|
// call would happen to initialized it (calling out to libuv),
|
|
|
|
// and the FFI call needs 2MB of stack when we just ran out.
|
|
|
|
|
2014-12-07 02:34:37 +00:00
|
|
|
rterrln!("\nthread '{}' has overflowed its stack",
|
|
|
|
Thread::current().name().unwrap_or("<unknown>"));
|
2014-11-24 03:21:17 +00:00
|
|
|
}
|