Skip to content

Commit 6174f9a

Browse files
committed
std: Move change_dir_locked to unstable. #7870
1 parent 4beda4e commit 6174f9a

File tree

4 files changed

+57
-43
lines changed

4 files changed

+57
-43
lines changed

src/libextra/tempfile.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ mod tests {
4848
fn recursive_mkdir_rel() {
4949
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
5050
use std::os;
51+
use std::unstable::change_dir_locked;
5152

5253
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel").
5354
expect("recursive_mkdir_rel");
54-
assert!(do os::change_dir_locked(&root) {
55+
assert!(do change_dir_locked(&root) {
5556
let path = Path("frob");
5657
debug!("recursive_mkdir_rel: Making: %s in cwd %s [%?]", path.to_str(),
5758
os::getcwd().to_str(),
@@ -78,10 +79,11 @@ mod tests {
7879
fn recursive_mkdir_rel_2() {
7980
use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
8081
use std::os;
82+
use std::unstable::change_dir_locked;
8183

8284
let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel_2").
8385
expect("recursive_mkdir_rel_2");
84-
assert!(do os::change_dir_locked(&root) {
86+
assert!(do change_dir_locked(&root) {
8587
let path = Path("./frob/baz");
8688
debug!("recursive_mkdir_rel_2: Making: %s in cwd %s [%?]", path.to_str(),
8789
os::getcwd().to_str(), os::path_exists(&path));

src/librustpkg/tests.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -791,12 +791,14 @@ fn rust_path_test() {
791791
792792
#[test]
793793
fn rust_path_contents() {
794+
use std::unstable::change_dir_locked;
795+
794796
let dir = mkdtemp(&os::tmpdir(), "rust_path").expect("rust_path_contents failed");
795797
let abc = &dir.push("A").push("B").push("C");
796798
assert!(os::mkdir_recursive(&abc.push(".rust"), U_RWX));
797799
assert!(os::mkdir_recursive(&abc.pop().push(".rust"), U_RWX));
798800
assert!(os::mkdir_recursive(&abc.pop().pop().push(".rust"), U_RWX));
799-
assert!(do os::change_dir_locked(&dir.push("A").push("B").push("C")) {
801+
assert!(do change_dir_locked(&dir.push("A").push("B").push("C")) {
800802
let p = rust_path();
801803
let cwd = os::getcwd().push(".rust");
802804
let parent = cwd.pop().pop().push(".rust");

src/libstd/os.rs

-40
Original file line numberDiff line numberDiff line change
@@ -863,46 +863,6 @@ pub fn change_dir(p: &Path) -> bool {
863863
}
864864
}
865865

866-
/// Changes the current working directory to the specified
867-
/// path while acquiring a global lock, then calls `action`.
868-
/// If the change is successful, releases the lock and restores the
869-
/// CWD to what it was before, returning true.
870-
/// Returns false if the directory doesn't exist or if the directory change
871-
/// is otherwise unsuccessful.
872-
/// FIXME #7870 This probably shouldn't be part of the public API
873-
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
874-
use task;
875-
use unstable::finally::Finally;
876-
877-
unsafe {
878-
// This is really sketchy. Using a pthread mutex so descheduling
879-
// in the `action` callback can cause deadlock. Doing it in
880-
// `task::atomically` to try to avoid that, but ... I don't know
881-
// this is all bogus.
882-
return do task::atomically {
883-
rust_take_change_dir_lock();
884-
885-
do (||{
886-
let old_dir = os::getcwd();
887-
if change_dir(p) {
888-
action();
889-
change_dir(&old_dir)
890-
}
891-
else {
892-
false
893-
}
894-
}).finally {
895-
rust_drop_change_dir_lock();
896-
}
897-
}
898-
}
899-
900-
extern {
901-
fn rust_take_change_dir_lock();
902-
fn rust_drop_change_dir_lock();
903-
}
904-
}
905-
906866
/// Copies a file from one location to another
907867
pub fn copy_file(from: &Path, to: &Path) -> bool {
908868
return do_copy_file(from, to);

src/libstd/unstable/mod.rs

+50
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,53 @@ extern {
7979
fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
8080
fn rust_raw_thread_join_delete(thread: *raw_thread);
8181
}
82+
83+
84+
/// Changes the current working directory to the specified
85+
/// path while acquiring a global lock, then calls `action`.
86+
/// If the change is successful, releases the lock and restores the
87+
/// CWD to what it was before, returning true.
88+
/// Returns false if the directory doesn't exist or if the directory change
89+
/// is otherwise unsuccessful.
90+
///
91+
/// This is used by test cases to avoid cwd races.
92+
///
93+
/// # Safety Note
94+
///
95+
/// This uses a pthread mutex so descheduling in the action callback
96+
/// can lead to deadlock. Calling change_dir_locked recursively will
97+
/// also deadlock.
98+
pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
99+
use os;
100+
use os::change_dir;
101+
use task;
102+
use unstable::finally::Finally;
103+
104+
unsafe {
105+
// This is really sketchy. Using a pthread mutex so descheduling
106+
// in the `action` callback can cause deadlock. Doing it in
107+
// `task::atomically` to try to avoid that, but ... I don't know
108+
// this is all bogus.
109+
return do task::atomically {
110+
rust_take_change_dir_lock();
111+
112+
do (||{
113+
let old_dir = os::getcwd();
114+
if change_dir(p) {
115+
action();
116+
change_dir(&old_dir)
117+
}
118+
else {
119+
false
120+
}
121+
}).finally {
122+
rust_drop_change_dir_lock();
123+
}
124+
}
125+
}
126+
127+
extern {
128+
fn rust_take_change_dir_lock();
129+
fn rust_drop_change_dir_lock();
130+
}
131+
}

0 commit comments

Comments
 (0)