Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extra::tempfile::TempDir causes IoError during Drop #10462

Closed
klutzy opened this issue Nov 13, 2013 · 6 comments
Closed

extra::tempfile::TempDir causes IoError during Drop #10462

klutzy opened this issue Nov 13, 2013 · 6 comments

Comments

@klutzy
Copy link
Contributor

klutzy commented Nov 13, 2013

use std::os;
use extra::tempfile::TempDir;
fn main() {
    let temp_dir = TempDir::new("asdf").unwrap();
    os::change_dir(temp_dir.path());
}
task '<main>' failed at 'Unhandled condition: io_error:
io::IoError{kind: OtherIoError, desc: "resource busy or locked", detail: None}',

TempDir has Drop implementation of calling rmdir the dir, but it may fail (platform-dependent) if the task change_dired.
part of #10452: run-pass/glob-std.rs.

@klutzy
Copy link
Contributor Author

klutzy commented Nov 13, 2013

I initially thought this would work:

 pub struct TempDir {
     priv path: Option<Path>
+    priv tmpdir: ~Path
 }
...

     pub fn new_in(tmpdir: &Path, suffix: &str) -> Option<TempDir> {
...
-                Ok(()) => return Some(TempDir { path: Some(p) })
+                Ok(()) => return Some(TempDir { path: Some(p), tmpdir: tmpdir.clone() })
...
     }
...
 impl Drop for TempDir {
     fn drop(&mut self) {
        for path in self.path.iter() {
            if path.exists() {
+               os::change_dir(tmpdir);
                fs::rmdir_recursive(path);
            }
        }
     }

but I realized that os::change_dir is not task-safe: #10463

@alexcrichton
Copy link
Member

It would seem to me that the most reasonable thing to do would to be just ignore the error in the destructor of TempDir. It's also a real possibility that someone else removed it, but it's just a temporary thing that should do its best to go away. If you changed directories into that directory, then I think that it's then your responsibility for removing it.

@ben0x539
Copy link
Contributor

I don't think unconditionally changing directories in the destructor is appropriate, but I'm not happy about silently leaving temporary directories lying around.

The destructor could check whether the current working directory is a subdirectory of the one it's going to delete and only if so change directory to its parent directory, but then we're still transparently changing directories in a destructor, which I'm pretty sure is going to catch most people by surprise.

I'd suggest we should just fail on all platforms in that case, but then we're failing in a destructor and callers pretty much need to do their own RAII for chdir'ing into and out of the temp dir to avoid unwinding while still in the temp dir and then aborting. :(

@klutzy
Copy link
Contributor Author

klutzy commented Nov 14, 2013

I started to think the real issue is that user does not easily recognize TempDir::drop() will occur. What about adding tempfile::with_temp_dir() function like this? (not tested)

fn with_temp_dir<T>(base: &Path, suffix: &str, f: |temp_dir: &Path| -> T) -> T {
    let prev_path = os::getcwd();
    let temp_dir = TempDir::new_in(base, suffix);
    os::change_dir(temp_dir.path());
    let result = f(temp_dir.path());
    os::change_dir(prev_path);
    fs::rmdir_recursive(temp_dir);
    result
}

klutzy added a commit to klutzy/rust that referenced this issue Nov 14, 2013
Rename {struct-update,fsu}-moves-and-copies, since win32
failed to run the test since UAC prevents any executable whose
name contaning "update". (rust-lang#10452)

Some tests related to rust-lang#9205 are expected to fail on gcc 4.8,
so they are marked as `xfail-win32` instead of `xfail-fast`.

Some tests using `extra::tempfile` fail on win32 due to rust-lang#10462.
Mark them as `xfail-win32`.
@alexcrichton
Copy link
Member

cc #12628

@alexcrichton
Copy link
Member

Since opening the drop implementation of TempDir has been modified to respect the semantics of not panicking on drop and ignoring I/O errors, so I'm going to close this.

flip1995 pushed a commit to flip1995/rust that referenced this issue Jun 30, 2023
…s,xFrednet

consider autoderef through user-defined `Deref` in `eager_or_lazy`

Fixes rust-lang#10462

This PR handles autoderef in the `eager_or_lazy` util module and stops suggesting to change lazy to eager if autoderef in an expression goes through user defined `Deref` impls, e.g.
```rs
struct S;
impl Deref for S {
  type Target = ();
  fn deref(&self) -> &Self::Target { &() }
}

let _ = Some(()).as_ref().unwrap_or_else(|| &S); // autoderef `&S` -> `&()`
```

changelog: [`unnecessary_lazy_evaluations`]: don't suggest changing lazy evaluation to eager if autoderef goes through user-defined `Deref`

r? `@xFrednet`  (because of the earlier review in rust-lang#10864, might help for context here)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants