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(),
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));
#[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");
}
}
-/// 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);
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();
+ }
+}