@@ -869,26 +869,38 @@ pub fn change_dir(p: &Path) -> bool {
869869/// CWD to what it was before, returning true.
870870/// Returns false if the directory doesn't exist or if the directory change
871871/// is otherwise unsuccessful.
872+ /// FIXME #7870 This probably shouldn't be part of the public API
872873pub fn change_dir_locked ( p : & Path , action : & fn ( ) ) -> bool {
873- use unstable:: global:: global_data_clone_create;
874- use unstable:: sync:: { Exclusive , exclusive} ;
875-
876- fn key ( _: Exclusive < ( ) > ) { }
874+ use task;
875+ use unstable:: finally:: Finally ;
877876
878877 unsafe {
879- let result = global_data_clone_create ( key, || { ~exclusive ( ( ) ) } ) ;
880-
881- do result. with_imm ( ) |_| {
882- let old_dir = os:: getcwd ( ) ;
883- if change_dir ( p) {
884- action ( ) ;
885- change_dir ( & old_dir)
886- }
887- else {
888- false
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 ( ) ;
889896 }
890897 }
891898 }
899+
900+ extern {
901+ fn rust_take_change_dir_lock ( ) ;
902+ fn rust_drop_change_dir_lock ( ) ;
903+ }
892904}
893905
894906/// Copies a file from one location to another
0 commit comments