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

Fix #1762 #1861

Merged
merged 1 commit into from Mar 2, 2018
Merged

Fix #1762 #1861

merged 1 commit into from Mar 2, 2018

Conversation

lheckemann
Copy link
Member

nix-store --export, nix-store --dump, and nix dump-path would previously
fail silently if writing the data out failed, because
a) FdSink::write ignored exceptions, and
b) the commands relied on FdSink's destructor, which ignores
exceptions, to flush the data out.

This could cause rather opaque issues with installing nixos, because
nix-store --export would happily proceed even if it couldn't write its
data out (e.g. if nix-store --import on the other side of the pipe
failed).

This commit adds tests that expose these issues in the nix-store
commands, and fixes them for all three.

@@ -67,7 +67,8 @@ void FdSink::write(const unsigned char * data, size_t len)
try {
writeFull(fd, data, len);
} catch (SysError & e) {
_good = true;
_good = false;
throw e;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just throw;?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, if that's equivalent or better. I'm a bit fuzzy on C++'s exception semantics.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure it's generally preferred, but I'm similarly reluctant to pose as a C++ semantics expert :). As I understand it, throw e will possibly (maybe always?) create a copy of the exception object which is usually unnecessary and can cause slicing if the object was a derived class from the caught type. I'm not sure in this case there is a problem but I just remember to just use "throw;" whenever possible :).

nix-store --export, nix-store --dump, and nix dump-path would previously
fail silently if writing the data out failed, because
 a) FdSink::write ignored exceptions, and
 b) the commands relied on FdSink's destructor, which ignores
    exceptions, to flush the data out.

This could cause rather opaque issues with installing nixos, because
nix-store --export would happily proceed even if it couldn't write its
data out (e.g. if nix-store --import on the other side of the pipe
failed).

This commit adds tests that expose these issues in the nix-store
commands, and fixes them for all three.
@dtzWill
Copy link
Member

dtzWill commented Feb 13, 2018

It seems it should be an error to destruct an FdSink without first calling flush(), then?

Not to burden this PR with "fix all the things" but just for sake of discussion/overall code goodness:

  • Other uses of FdSink (remote-store, ssh-store)-- do these need to be similarly adjusted to not rely on I/O performed in the destructor?
  • Is there a clean way to catch when things aren't handled properly? In the code you touched it's trivial to see that a call to flush() post-dominates on all non-error paths, but in more complicated code it might be more difficult. Catching these actively would be helpful to ensure there aren't lurking edge-case bugs along less commonly used paths.

Towards the latter, perhaps FdSink should grow a "finish" like the compression sinks have, which would help differentiate flush vs what's essentially explicitly performing what's currently done in the destructors (minus ignoring exceptions).


All that said, this LGTM!

@lheckemann
Copy link
Member Author

I checked for other uses of FdSink and they all seem to call flush as appropriate. nix dump-path was one I only discovered because of that grep. I'm not sure how to handle this overall. There may be cases where we want to ignore failure on the destruction flush?

@lheckemann
Copy link
Member Author

@edolstra ?

Copy link
Member

@shlevy shlevy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an unambiguous improvement over the status quo, we can look at larger-scale improvements separately.

@shlevy shlevy merged commit 78ac3eb into NixOS:master Mar 2, 2018
@lheckemann lheckemann deleted the write-failure-fixes branch March 2, 2018 16:16
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

Successfully merging this pull request may close these issues.

None yet

3 participants