Skip to content

Lint for types where cleanup before drop is desirable #32677

Open
@stepancheg

Description

@stepancheg

BufWriter.drop is broken.

BufWriter flushes data on drop and ignores the result. It is incorrect for two reasons:

  • you must not ignore write errors. For example, when filesystem is full, write fails. Currently last write error is quietly ignored. This code demonstrates the problem: http://is.gd/ZdgbF9
  • drop may indefinitly hang, for example, if BufWrtiter underlying stream is socket, and nobody reads on the other side

Generally, I think any drop must only release resources, do not do anything blocking or failing.

The similar issue was only partially fixed in #30888.

We (together with @cfallin) propose a solution:

Proposed solution

Add another function to BufWriter (and probably to Write trait): cancel. User of BufWriter must explicitly call either flush or cancel prior to drop.

struct BufWriter gets unfinished flag instead of panicked.

BufWriter.write unconditionally sets unfinished = true.

BufWriter.flush or BufWriter.cancel unconditionally set unfinished = false.

And finally, BufWriter.drop becomes an assertion:

impl Drop for BufWriter {
    fn drop(&mut self) {
        // check `flush` or `cancel` is explicitly called
        // but it is OK to discard buffer on panic
        assert!(!self.unfinished || std::thread::panicking());
    }
}

That change is backward incompatible, however, it is not that bad: developer will likely get panic on first program run, and can quickly fix the code.

Change could be transitional: no-op cancel function could be added in rust version current+1 and assertion added in rust version current+2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions