mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
Fix a bug with the scheduler and destructor order
The PausibleIdleCallback must have some handle into the event loop, and because struct destructors are run in order of top-to-bottom in order of fields, this meant that the event loop was getting destroyed before the idle callback was getting destroyed. I can't confirm that this fixes a problem in how we use libuv, but it does semantically fix a problem for usage with other event loops.
This commit is contained in:
parent
3f5b2219cc
commit
3b30377e14
@ -85,7 +85,17 @@ pub struct Scheduler {
|
||||
priv yield_check_count: uint,
|
||||
/// A flag to tell the scheduler loop it needs to do some stealing
|
||||
/// in order to introduce randomness as part of a yield
|
||||
priv steal_for_yield: bool
|
||||
priv steal_for_yield: bool,
|
||||
|
||||
// n.b. currently destructors of an object are run in top-to-bottom in order
|
||||
// of field declaration. Due to its nature, the pausible idle callback
|
||||
// must have some sort of handle to the event loop, so it needs to get
|
||||
// destroyed before the event loop itself. For this reason, we destroy
|
||||
// the event loop last to ensure that any unsafe references to it are
|
||||
// destroyed before it's actually destroyed.
|
||||
|
||||
/// The event loop used to drive the scheduler and perform I/O
|
||||
event_loop: ~EventLoopObject,
|
||||
}
|
||||
|
||||
/// An indication of how hard to work on a given operation, the difference
|
||||
|
52
src/test/run-pass/field-destruction-order.rs
Normal file
52
src/test/run-pass/field-destruction-order.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// 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.
|
||||
|
||||
// In theory, it doesn't matter what order destructors are run in for rust
|
||||
// because we have explicit ownership of values meaning that there's no need to
|
||||
// run one before another. With unsafe code, however, there may be a safe
|
||||
// interface which relies on fields having their destructors run in a particular
|
||||
// order. At the time of this writing, std::rt::sched::Scheduler is an example
|
||||
// of a structure which contains unsafe handles to FFI-like types, and the
|
||||
// destruction order of the fields matters in the sense that some handles need
|
||||
// to get destroyed before others.
|
||||
//
|
||||
// In C++, destruction order happens bottom-to-top in order of field
|
||||
// declarations, but we currently run them top-to-bottom. I don't think the
|
||||
// order really matters that much as long as we define what it is.
|
||||
|
||||
struct A;
|
||||
struct B;
|
||||
struct C {
|
||||
a: A,
|
||||
b: B,
|
||||
}
|
||||
|
||||
static mut hit: bool = false;
|
||||
|
||||
impl Drop for A {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
assert!(!hit);
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for B {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
assert!(hit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let _c = C { a: A, b: B };
|
||||
}
|
Loading…
Reference in New Issue
Block a user