std: Move change_dir_locked to unstable. #7870
This commit is contained in:
parent
4beda4e582
commit
6174f9a4d9
@ -48,10 +48,11 @@ mod tests {
|
||||
fn recursive_mkdir_rel() {
|
||||
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
use std::os;
|
||||
use std::unstable::change_dir_locked;
|
||||
|
||||
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel").
|
||||
expect("recursive_mkdir_rel");
|
||||
assert!(do os::change_dir_locked(&root) {
|
||||
assert!(do change_dir_locked(&root) {
|
||||
let path = Path("frob");
|
||||
debug!("recursive_mkdir_rel: Making: %s in cwd %s [%?]", path.to_str(),
|
||||
os::getcwd().to_str(),
|
||||
@ -78,10 +79,11 @@ mod tests {
|
||||
fn recursive_mkdir_rel_2() {
|
||||
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
|
||||
use std::os;
|
||||
use std::unstable::change_dir_locked;
|
||||
|
||||
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel_2").
|
||||
expect("recursive_mkdir_rel_2");
|
||||
assert!(do os::change_dir_locked(&root) {
|
||||
assert!(do change_dir_locked(&root) {
|
||||
let path = Path("./frob/baz");
|
||||
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s [%?]", path.to_str(),
|
||||
os::getcwd().to_str(), os::path_exists(&path));
|
||||
|
@ -791,12 +791,14 @@ fn rust_path_test() {
|
||||
|
||||
#[test]
|
||||
fn rust_path_contents() {
|
||||
use std::unstable::change_dir_locked;
|
||||
|
||||
let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
|
||||
let abc = &dir.push("A").push("B").push("C");
|
||||
assert!(os::mkdir_recursive(&abc.push(".rust"), U_RWX));
|
||||
assert!(os::mkdir_recursive(&abc.pop().push(".rust"), U_RWX));
|
||||
assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), U_RWX));
|
||||
assert!(do os::change_dir_locked(&dir.push("A").push("B").push("C")) {
|
||||
assert!(do change_dir_locked(&dir.push("A").push("B").push("C")) {
|
||||
let p = rust_path();
|
||||
let cwd = os::getcwd().push(".rust");
|
||||
let parent = cwd.pop().pop().push(".rust");
|
||||
|
@ -863,46 +863,6 @@ pub fn change_dir(p: &Path) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Changes the current working directory to the specified
|
||||
/// path while acquiring a global lock, then calls `action`.
|
||||
/// If the change is successful, releases the lock and restores the
|
||||
/// CWD to what it was before, returning true.
|
||||
/// Returns false if the directory doesn't exist or if the directory change
|
||||
/// is otherwise unsuccessful.
|
||||
/// FIXME #7870 This probably shouldn't be part of the public API
|
||||
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
|
||||
use task;
|
||||
use unstable::finally::Finally;
|
||||
|
||||
unsafe {
|
||||
// This is really sketchy. Using a pthread mutex so descheduling
|
||||
// in the `action` callback can cause deadlock. Doing it in
|
||||
// `task::atomically` to try to avoid that, but ... I don't know
|
||||
// this is all bogus.
|
||||
return do task::atomically {
|
||||
rust_take_change_dir_lock();
|
||||
|
||||
do (||{
|
||||
let old_dir = os::getcwd();
|
||||
if change_dir(p) {
|
||||
action();
|
||||
change_dir(&old_dir)
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).finally {
|
||||
rust_drop_change_dir_lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_take_change_dir_lock();
|
||||
fn rust_drop_change_dir_lock();
|
||||
}
|
||||
}
|
||||
|
||||
/// Copies a file from one location to another
|
||||
pub fn copy_file(from: &Path, to: &Path) -> bool {
|
||||
return do_copy_file(from, to);
|
||||
|
@ -79,3 +79,53 @@ extern {
|
||||
fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
|
||||
fn rust_raw_thread_join_delete(thread: *raw_thread);
|
||||
}
|
||||
|
||||
|
||||
/// Changes the current working directory to the specified
|
||||
/// path while acquiring a global lock, then calls `action`.
|
||||
/// If the change is successful, releases the lock and restores the
|
||||
/// CWD to what it was before, returning true.
|
||||
/// Returns false if the directory doesn't exist or if the directory change
|
||||
/// is otherwise unsuccessful.
|
||||
///
|
||||
/// This is used by test cases to avoid cwd races.
|
||||
///
|
||||
/// # Safety Note
|
||||
///
|
||||
/// This uses a pthread mutex so descheduling in the action callback
|
||||
/// can lead to deadlock. Calling change_dir_locked recursively will
|
||||
/// also deadlock.
|
||||
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
|
||||
use os;
|
||||
use os::change_dir;
|
||||
use task;
|
||||
use unstable::finally::Finally;
|
||||
|
||||
unsafe {
|
||||
// This is really sketchy. Using a pthread mutex so descheduling
|
||||
// in the `action` callback can cause deadlock. Doing it in
|
||||
// `task::atomically` to try to avoid that, but ... I don't know
|
||||
// this is all bogus.
|
||||
return do task::atomically {
|
||||
rust_take_change_dir_lock();
|
||||
|
||||
do (||{
|
||||
let old_dir = os::getcwd();
|
||||
if change_dir(p) {
|
||||
action();
|
||||
change_dir(&old_dir)
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
}).finally {
|
||||
rust_drop_change_dir_lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_take_change_dir_lock();
|
||||
fn rust_drop_change_dir_lock();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user