Thread: Return value of PathNameOpenFile()

Return value of PathNameOpenFile()

From
Antonin Houska
Date:
I've noticed that some callers of PathNameOpenFile()
(e.g. bbsink_server_begin_archive()) consider the call failed even if the
function returned zero, while other ones do check whether the file descriptor
is strictly negative. Since the file descriptor is actually returned by the
open() system call, I assume that zero is a valid result, isn't it?

-- 
Antonin Houska
Web: https://www.cybertec-postgresql.com



Re: Return value of PathNameOpenFile()

From
Daniel Gustafsson
Date:
> On 6 Sep 2022, at 09:26, Antonin Houska <ah@cybertec.at> wrote:
>
> I've noticed that some callers of PathNameOpenFile()
> (e.g. bbsink_server_begin_archive()) consider the call failed even if the
> function returned zero, while other ones do check whether the file descriptor
> is strictly negative. Since the file descriptor is actually returned by the
> open() system call, I assume that zero is a valid result, isn't it?

Agreed, zero should be valid as it's a non-negative integer.  However, callers
in fd.c are themselves checking for (fd <= 0) in some cases, and some have done
so since the very early days of the codebase, so I wonder if there historically
used to be a platform which considered 0 an invalid fd?

--
Daniel Gustafsson        https://vmware.com/




Re: Return value of PathNameOpenFile()

From
Tom Lane
Date:
Daniel Gustafsson <daniel@yesql.se> writes:
> Agreed, zero should be valid as it's a non-negative integer.  However, callers
> in fd.c are themselves checking for (fd <= 0) in some cases, and some have done
> so since the very early days of the codebase, so I wonder if there historically
> used to be a platform which considered 0 an invalid fd?

I'm betting it's a thinko that never got caught because 0 would
always be taken up by stdin.  Maybe you'd notice if you tried to
close-and-reopen stdin, but that's not something the server ever does.

            regards, tom lane



Re: Return value of PathNameOpenFile()

From
Daniel Gustafsson
Date:
> On 6 Sep 2022, at 16:12, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Daniel Gustafsson <daniel@yesql.se> writes:
>> Agreed, zero should be valid as it's a non-negative integer.  However, callers
>> in fd.c are themselves checking for (fd <= 0) in some cases, and some have done
>> so since the very early days of the codebase, so I wonder if there historically
>> used to be a platform which considered 0 an invalid fd?
>
> I'm betting it's a thinko that never got caught because 0 would
> always be taken up by stdin.  Maybe you'd notice if you tried to
> close-and-reopen stdin, but that's not something the server ever does.

Doh, of course.  The attached is a quick (lightly make check tested) take on
allowing 0, but I'm not sure that's what we want?

--
Daniel Gustafsson        https://vmware.com/


Attachment

Re: Return value of PathNameOpenFile()

From
Tom Lane
Date:
Daniel Gustafsson <daniel@yesql.se> writes:
> Doh, of course.  The attached is a quick (lightly make check tested) take on
> allowing 0, but I'm not sure that's what we want?

Actually, wait a second.  At least some of these are not dealing
with kernel FDs but with our "virtual FD" abstraction.  For those,
zero is indeed an invalid value.  There might well be some "<= 0"
versus "< 0" errors in this area, but it requires closer inspection.

            regards, tom lane



Re: Return value of PathNameOpenFile()

From
Daniel Gustafsson
Date:
> On 6 Sep 2022, at 21:44, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Daniel Gustafsson <daniel@yesql.se> writes:
>> Doh, of course.  The attached is a quick (lightly make check tested) take on
>> allowing 0, but I'm not sure that's what we want?
>
> Actually, wait a second.  At least some of these are not dealing
> with kernel FDs but with our "virtual FD" abstraction.  For those,
> zero is indeed an invalid value.

Yes and no, I think; PathNameOpenFile kind of returns a Vfd on success but a
kernel fd on failure which makes this a bit confusing.  Abbreviated for space,
the code looks like this:

    file = AllocateVfd();
    vfdP = &VfdCache[file];
    ...

    vfdP->fd = BasicOpenFilePerm(fileName, fileFlags, fileMode);

    if (vfdP->fd < 0)
    {
        ...
        return -1;
    }

    ...
    return file;

So if the underlying BasicOpenFilePerm fails then open(2) failed and we return
-1, which is what open(2) returned.  If it succeeds, then we return the Vfd
returned by AllocateVfd which can never be zero, as thats the VFD_CLOSED
ringbuffer anchor.  Since AllocateVfd doesn't return on error, it's easy to
confuse oneself on exactly which error is propagated.

Checking for (fd <= 0) on an fd returned from PathNameOpenFile is thus not
wrong, albeit wearing both belts and suspenders since it can never return 0.
Changing them seem like codechurn for no reason even if the check for 0 is
superfluous.  The callsites that only check for (fd < 0) are equally correct,
and need not be changed.

Callers of BasicOpenFile need however allow for zero since they get the kernel
fd back, which AFAICT from scanning that they all do.

So in summary, I can't spot a callsite which isn't safe.

--
Daniel Gustafsson        https://vmware.com/