@@ -869,26 +869,38 @@ pub fn change_dir(p: &Path) -> bool {
869
869
/// CWD to what it was before, returning true.
870
870
/// Returns false if the directory doesn't exist or if the directory change
871
871
/// is otherwise unsuccessful.
872
+ /// FIXME #7870 This probably shouldn't be part of the public API
872
873
pub 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 ;
877
876
878
877
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 ( ) ;
889
896
}
890
897
}
891
898
}
899
+
900
+ extern {
901
+ fn rust_take_change_dir_lock ( ) ;
902
+ fn rust_drop_change_dir_lock ( ) ;
903
+ }
892
904
}
893
905
894
906
/// Copies a file from one location to another
0 commit comments