Skip to content

Commit fe993fd

Browse files
committed
De-stabilize thread::scoped and friends
Issue #24292 demonstrates that the `scoped` API as currently offered can be memory-unsafe: the `JoinGuard` can be moved into a context that will fail to execute destructors prior to the stack frame being popped (for example, by creating an `Rc` cycle). This commit reverts the APIs to `unstable` status while a long-term solution is worked out. (There are several possible ways to address this issue; it's not a fundamental problem with the `scoped` idea, but rather an indication that Rust doesn't currently provide a good way to ensure that destructors are run within a particular stack frame.)
1 parent 588d37c commit fe993fd

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

src/libstd/thread/mod.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ impl Builder {
274274
/// Unlike the `scoped` free function, this method yields an
275275
/// `io::Result` to capture any failure to create the thread at
276276
/// the OS level.
277-
#[stable(feature = "rust1", since = "1.0.0")]
277+
#[unstable(feature = "scoped",
278+
reason = "memory unsafe if destructor is avoided, see #24292")]
278279
pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
279280
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
280281
{
@@ -387,7 +388,8 @@ pub fn spawn<F>(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
387388
///
388389
/// Panics if the OS fails to create a thread; use `Builder::scoped`
389390
/// to recover from such errors.
390-
#[stable(feature = "rust1", since = "1.0.0")]
391+
#[unstable(feature = "scoped",
392+
reason = "memory unsafe if destructor is avoided, see #24292")]
391393
pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
392394
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
393395
{
@@ -674,7 +676,8 @@ impl Drop for JoinHandle {
674676
/// handle: the ability to join a child thread is a uniquely-owned
675677
/// permission.
676678
#[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
677-
#[stable(feature = "rust1", since = "1.0.0")]
679+
#[unstable(feature = "scoped",
680+
reason = "memory unsafe if destructor is avoided, see #24292")]
678681
pub struct JoinGuard<'a, T: Send + 'a> {
679682
inner: JoinInner<T>,
680683
_marker: PhantomData<&'a T>,
@@ -706,7 +709,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> {
706709
}
707710

708711
#[unsafe_destructor]
709-
#[stable(feature = "rust1", since = "1.0.0")]
712+
#[unstable(feature = "scoped",
713+
reason = "memory unsafe if destructor is avoided, see #24292")]
710714
impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
711715
fn drop(&mut self) {
712716
if !self.inner.joined {

0 commit comments

Comments
 (0)