Re-explaining that errno thing....
Michael Adam
obnox at samba.org
Mon Feb 27 08:19:25 UTC 2017
On 2017-02-26 at 16:32 -0800, Jeremy Allison wrote:
> On Sun, Feb 26, 2017 at 07:28:19AM +0200, Uri Simchoni wrote:
> > Jeremy,
> >
> > I thought I understood commit cda6764f1a8db96182bfd1855440bc6a1ba1abee,
> > which is about correctness of errno in failures in vfs_shadow_copy2, but
> > yesterday, when reviewing Ralph / Metze's vfs_catia patch, I found out
> > that I can't explain to myself why always saving errno and restoring it
> > is incorrect (there's this pattern in that patch).
> >
> > So, commit cda6764f1a8db96182bfd1855440bc6a1ba1abee says that the way to
> > deal with errors is:
> >
> > int save_errno = 0;
> >
> > if (error) {
> > save_errno = errno;
> > goto out;
> > }
> >
> > out:
> > ...do some cleanup
> > if (save_errno) {
> > errno = save_errno;
> > }
> > return ret;
> >
> >
> > Whereas the previous pattern was:
> >
> > int save_errno;
> >
> > if (error) {
> > goto out;
> > }
> >
> > out:
> > save_errno = errno;
> > ...do some cleanup
> > errno = save_errno;
> > return ret;
> >
> >
> > The commit said code shouldn't be *setting* errno if there's no error.
> > Fine. But the "old" pattern isn't setting errno - it's keeping it the
> > way it was.
> >
> > The "old" pattern is less obviously correct, as errno has to be kept
> > untouched from the failure point up to the start of cleanup. But it
> > seems to me like the pattern itself doesn't break anything (it just lets
> > code around it break things).
> >
> > Is that analysis correct or am I missing something again?
>
> Errr. Probably not, it's just the the 'old' pattern *looks*
> much more dangerous to me :-).
>
> I really don't like to touch something - especially something
> that's a global (or thread-local storage) unless I know I need
> to change it.
>
> So depending on the code surrounding it, the "old" pattern
> probably is safe, it's just that IMHO new code should be
> using the new pattern, as that is much clearer on what is
> being changed when.
>
> It's a matter or continually raising the code quality IMHO,
> and to me, pattern #1 is better.
I personally find the old pattern more obvious, in the sense
that the errno bracket around the cleanup code is much more
obvious.
But it has 2 issues:
1) As Uri said, the erroring-out code must make sure that
between the failed call and the goto out, there is no
errno-changing call.
2) The way it is written, it may be setting errno in cases
where it would not be needed (errno == 0).
This could of course be fixed with adding if (saved_errno) ...
as in the old pattern.
On the other hand side, this may be desired if for instance
the failing operation did not produce an errno, but the
cleanup code did set an errno... Not sure what's better
in this situation.
The new pattern has issues:
1) Because errno handling is scattered, it duplicates code
and is less obvious (to me). And the programmer must
always remember to save the errno at each failure point.
2) The reverse of issue #2 above: If there was no errno
in the originally failing code, but there is an errno
in the cleanup code, then the cleanup code's errno will
be set at exit. That may or may not be desired.
So, I'd say neither approach is perfect. I personally
tend to prefer a variant of the old pattern.
My 2 cents..
Michael
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 163 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170227/dfc81bc4/signature.sig>
More information about the samba-technical
mailing list