Skip to content

Fix: Proper error handling for file:open() call in couch_file.erl#1164

Merged
janl merged 3 commits into
apache:masterfrom
Spotme:spotme/couch_file_fix
Mar 9, 2018
Merged

Fix: Proper error handling for file:open() call in couch_file.erl#1164
janl merged 3 commits into
apache:masterfrom
Spotme:spotme/couch_file_fix

Conversation

@AlexanderKaraberov

@AlexanderKaraberov AlexanderKaraberov commented Feb 14, 2018

Copy link
Copy Markdown
Contributor

Overview

According to Erlang's file:open docs this function returns {error, Reason} in case of failure but inside couch_file:sync and init functions there are no checks for this in two places. Consequently when I received {error, emfile} kind of error, process crashed with badmatch instead of a proper error.

Testing recommendations

Simulate {error, emfile} conditions (e.g. decrease ulimit on your OS) and observe an error.

Checklist

  • Code is written and works correctly;
  • Changes are covered by tests;
  • Documentation reflects the changes;

@janl janl added this to the 2.2.0 milestone Feb 28, 2018
@rnewson

rnewson commented Mar 6, 2018

Copy link
Copy Markdown
Member

-1.

We assert that we get the ok we expect. If we don't, we want the process to crash, which it does.

Adding error handling code for errors we don't intend to handle (in the sync case, you immediately throw it anyway) is an anti-pattern in erlang, though common (or mandatory) in other languages.

@rnewson

rnewson commented Mar 6, 2018

Copy link
Copy Markdown
Member

@davisp if you would like to comment on the init portions.

@davisp davisp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good for the most part. Just a few style nits that need straightening out.

Comment thread src/couch/src/couch_file.erl Outdated
{ok, Fd} = file:open(Filepath, [append, raw]),
try ok = file:sync(Fd) after ok = file:close(Fd) end;
case file:open(Filepath, [append, raw]) of
{ok, Fd} ->

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Use four space indents everywhere.

Comment thread src/couch/src/couch_file.erl Outdated
{ok, Fd} ->
try ok = file:sync(Fd) after ok = file:close(Fd) end;
Error ->
throw(Error)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Match {error, Error} and then erlang:error(Error) here.

@davisp

davisp commented Mar 6, 2018

Copy link
Copy Markdown
Member

@rnewson yes and no. The issue is where we want that badmatch to happen and with what as the badmatch. For the init section this is a good change as it matches the initial open. What's being added is the handling when the second of two fails to behave the same as the first. This is fine as we already handle the error. And it cleans up logs a bit in that the emfile error happens in the process doing the open rather than a EXIT/DOWN message when the couch_file pid dies on a badmatch.

As for the init process this just reuses the existing logic which seems cleaner than going back and rewriting it to use proc_lib properly.

+1 after style issues are addressed

@rnewson

rnewson commented Mar 6, 2018

Copy link
Copy Markdown
Member

if @davisp is happy, I'm happy.

Comment thread src/couch/src/couch_file.erl Outdated
try ok = file:sync(Fd) after ok = file:close(Fd) end;
{error, Error} ->
erlang:error(Error)
end;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This end should be dedented one level.

Comment thread src/couch/src/couch_file.erl Outdated
{ok, Eof} = file:position(Fd, eof),
erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
{ok, #file{fd=Fd, eof=Eof, is_sys=IsSys, pread_limit=Limit}};
case file:open(Filepath, OpenOptions) of

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You've got an extra space here.

Comment thread src/couch/src/couch_file.erl Outdated
{ok, #file{fd=Fd, eof=Eof, is_sys=IsSys, pread_limit=Limit}};
Error ->
init_status_error(ReturnPid, Ref, Error)
end;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And two extra spaces here.

@davisp davisp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1

@janl
janl merged commit f999071 into apache:master Mar 9, 2018
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.

4 participants