From 4beda4e582e4fe008aaf866a5f3ad6a20dec9876 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 17 Jul 2013 18:38:12 -0700 Subject: [PATCH] std::rt: Stop using unstable::global in change_dir_locked --- src/libstd/os.rs | 38 +++++++++++++++++++++++++------------- src/rt/rust_builtin.cpp | 12 ++++++++++++ src/rt/rustrt.def.in | 2 ++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 4bfd3bbcd3ff..fb5be0494ef0 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -869,26 +869,38 @@ pub fn change_dir(p: &Path) -> bool { /// 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 unstable::global::global_data_clone_create; - use unstable::sync::{Exclusive, exclusive}; - - fn key(_: Exclusive<()>) { } + use task; + use unstable::finally::Finally; unsafe { - let result = global_data_clone_create(key, || { ~exclusive(()) }); + // 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 result.with_imm() |_| { - let old_dir = os::getcwd(); - if change_dir(p) { - action(); - change_dir(&old_dir) - } - else { - false + 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 diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 863e0a3a99e1..4dde01d5f00c 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -947,6 +947,18 @@ rust_get_exit_status_newrt() { return exit_status; } +static lock_and_signal change_dir_lock; + +extern "C" CDECL void +rust_take_change_dir_lock() { + global_args_lock.lock(); +} + +extern "C" CDECL void +rust_drop_change_dir_lock() { + global_args_lock.unlock(); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 215673be1203..e9e0f3b69490 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -268,3 +268,5 @@ rust_take_global_args_lock rust_drop_global_args_lock rust_set_exit_status_newrt rust_get_exit_status_newrt +rust_take_change_dir_lock +rust_drop_change_dir_lock \ No newline at end of file