given an fd, how to tell if it's open?

  • Follow


Given an file descriptor that may or may not be open, what's the easiest and 
cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I tried 
using fstat() and fcntl(F_GETFL) and look for EBADF return and they work 
fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are there 
other ways to do this? Chris 


0
Reply Chris 11/20/2004 5:59:56 PM

Chris Markle wrote :

> Given an file descriptor that may or may not be open, what's the easiest and 
> cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I tried 
> using fstat() and fcntl(F_GETFL) and look for EBADF return and they work 
> fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are there 
> other ways to do this? Chris 

dup() or dup2() ?

-- 
DINH V. Hoa,

"monde de merde" -- Erwan David

0
Reply DINH 11/20/2004 6:04:01 PM


"Chris Markle" <cmarkle@sendmail.com> writes:

> Given an file descriptor that may or may not be open, what's the easiest and 
> cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I tried 
> using fstat() and fcntl(F_GETFL) and look for EBADF return and they work 
> fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are there 
> other ways to do this? Chris 

You might try lseek(), and look for the same error, if you're into
timing system calls.

-- 
M�ns Rullg�rd
mru@inprovide.com
0
Reply iso 11/20/2004 6:19:14 PM

M�ns Rullg�rd wrote :

> "Chris Markle" <cmarkle@sendmail.com> writes:
> 
> > Given an file descriptor that may or may not be open, what's the easiest and 
> > cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I tried 
> > using fstat() and fcntl(F_GETFL) and look for EBADF return and they work 
> > fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are there 
> > other ways to do this? Chris 
> 
> You might try lseek(), and look for the same error, if you're into
> timing system calls.

but lseek() won't work for streams :)

-- 
DINH V. Hoa,

"monde de merde" -- Erwan David

0
Reply DINH 11/20/2004 6:33:25 PM

M=E5ns Rullg=E5rd wrote:

> "Chris Markle" <cmarkle@sendmail.com> writes:
>=20
>=20
>>Given an file descriptor that may or may not be open, what's the easies=
t and=20
>>cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I tr=
ied=20
>>using fstat() and fcntl(F_GETFL) and look for EBADF return and they wor=
k=20
>>fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are ther=
e=20
>>other ways to do this? Chris=20
>=20
>=20
> You might try lseek(), and look for the same error, if you're into
> timing system calls.
>=20

Somewhat off-topic to the original post ...

But *why* does the OP need to know that piece of information?
If the program in question is so poorly coded that
the OP needs to check if a particular integer
value is a valid FD, I shudder to think of what
happens to allocated memory or to pointers
in that same code (unless he's looking to
track down an FD leak, e.g. missing close(),
someplace).

NPL

--=20
"It is impossible to make anything foolproof
because fools are so ingenious"
  - A. Bloch
0
Reply Nick 11/20/2004 6:42:31 PM

DINH Viet Hoa <dinh.viet.hoa@free.fr> writes:

> M�ns Rullg�rd wrote :
>
>> "Chris Markle" <cmarkle@sendmail.com> writes:
>> 
>> > Given an file descriptor that may or may not be open, what's the
>> > easiest and cheapest (least cpu, etc.) way to tell if it's "good"
>> > (i.e. open)? I tried using fstat() and fcntl(F_GETFL) and look
>> > for EBADF return and they work fine (fcntl on Sol seemed just
>> > slightly "cheaper" than fstat). Are there other ways to do this? 
>> > Chris
>> 
>> You might try lseek(), and look for the same error, if you're into
>> timing system calls.
>
> but lseek() won't work for streams :)

It will set errno to EISPIPE if the fd isn't seekable, and EBADF if it
isn't open at all, so it can be used to tell whether an fd is open.

-- 
M�ns Rullg�rd
mru@inprovide.com
0
Reply iso 11/20/2004 6:49:51 PM

"DINH Viet Hoa" <dinh.viet.hoa@free.fr> wrote in message 
news:etPan.419f8df5.47be063b.13fa@utopia...
> M�ns Rullg�rd wrote :
>
>> "Chris Markle" <cmarkle@sendmail.com> writes:
>>
>> > Given an file descriptor that may or may not be open, what's the 
>> > easiest and
>> > cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? I 
>> > tried
>> > using fstat() and fcntl(F_GETFL) and look for EBADF return and they 
>> > work
>> > fine (fcntl on Sol seemed just slightly "cheaper" than fstat). Are 
>> > there
>> > other ways to do this? Chris
>>
>> You might try lseek(), and look for the same error, if you're into
>> timing system calls.
>
> but lseek() won't work for streams :)

    That's the idea. It's not supposed to work, it's supposed to fail. All 
you care about is, did it fail because the file descriptor is invalid? Or 
did something else happen?

    The 'getsockopt' function is popular too, you either get -1/EBADF or you 
don't.

    DS


0
Reply David 11/20/2004 8:56:39 PM

Nick,

> Somewhat off-topic to the original post ...
> But *why* does the OP need to know that piece of information?
> If the program in question is so poorly coded that
> the OP needs to check if a particular integer
> value is a valid FD, I shudder to think of what
> happens to allocated memory or to pointers
> in that same code (unless he's looking to
> track down an FD leak, e.g. missing close(),
> someplace).

The OP (me) is dealing with OpenLDAP 2.1.x slapd which runs at a customer 
for 140 straight days then spins. The spin has only shown its head twice in 
a 6m period, so it's sorta hard to reproduce. The spin is related to 
select() suddenly being called on the 140th day with a fdset that contains 
apparently a closed fd. If we fix the loop in OpenLDAP (which we know how to 
do) then OpenLDAP will shutdown (instead of spin) after it gets 16 straight 
EBADF's from select(). That's a barely better option. We are reviewing 1 
zillion lines of OpenLDAP code to see if we can see where close() is being 
done without the associated cleanup, but may not find it. Until we do, we 
thought maybe if we "cleaned up" the fdset to rid it of closed files after 
we get this EBADF then maybe we could keep OpenLDAP running so the 
customer's 1.5million users stay happy. Not the best of circumstances but 
life's like that sometimes...

Chris


0
Reply Chris 11/20/2004 10:36:38 PM

Chris Markle wrote:
> Nick,
> 
> 
>>Somewhat off-topic to the original post ...
>>But *why* does the OP need to know that piece of information?
>>If the program in question is so poorly coded that
>>the OP needs to check if a particular integer
>>value is a valid FD, I shudder to think of what
>>happens to allocated memory or to pointers
>>in that same code (unless he's looking to
>>track down an FD leak, e.g. missing close(),
>>someplace).
> 
> 
> The OP (me) is dealing with OpenLDAP 2.1.x slapd which runs at a customer 
> for 140 straight days then spins. The spin has only shown its head twice in 
> a 6m period, so it's sorta hard to reproduce. The spin is related to 
> select() suddenly being called on the 140th day with a fdset that contains 
> apparently a closed fd. If we fix the loop in OpenLDAP (which we know how to 
> do) then OpenLDAP will shutdown (instead of spin) after it gets 16 straight 
> EBADF's from select(). That's a barely better option. We are reviewing 1 
> zillion lines of OpenLDAP code to see if we can see where close() is being 
> done without the associated cleanup, but may not find it. Until we do, we 
> thought maybe if we "cleaned up" the fdset to rid it of closed files after 
> we get this EBADF then maybe we could keep OpenLDAP running so the 
> customer's 1.5million users stay happy. Not the best of circumstances but 
> life's like that sometimes...
> 
> Chris
> 
> 
My apologies.  I jumped to an erroneous conclusion.




-- 
"It is impossible to make anything foolproof
because fools are so ingenious"
  - A. Bloch
0
Reply Nick 11/20/2004 11:04:00 PM

On Sat, 20 Nov 2004 22:36:38 +0000, Chris Markle wrote:

> done without the associated cleanup, but may not find it. Until we do, we 
> thought maybe if we "cleaned up" the fdset to rid it of closed files after 
> we get this EBADF then maybe we could keep OpenLDAP running so the 
> customer's 1.5million users stay happy. Not the best of circumstances but 
> life's like that sometimes...

 The easiest thing to do here is switch to poll() or even epoll(), and
then trigger off which fd returns as bad.
 It _should_ also be possible, with a small amount of work, to trace where
the fd that comes back as bad is coming from. Although from what I
remember of the Openldap code base, maybe that isn't so :(.

-- 
James Antill -- james@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

0
Reply James 11/20/2004 11:24:32 PM

"James Antill" <james-netnews@and.org> wrote in message 
news:pan.2004.11.20.23.24.32.594604@and.org...
> On Sat, 20 Nov 2004 22:36:38 +0000, Chris Markle wrote:
>
>> done without the associated cleanup, but may not find it. Until we do, we
>> thought maybe if we "cleaned up" the fdset to rid it of closed files 
>> after
>> we get this EBADF then maybe we could keep OpenLDAP running so the
>> customer's 1.5million users stay happy. Not the best of circumstances but
>> life's like that sometimes...
>
> The easiest thing to do here is switch to poll() or even epoll(), and
> then trigger off which fd returns as bad.
> It _should_ also be possible, with a small amount of work, to trace where
> the fd that comes back as bad is coming from. Although from what I
> remember of the Openldap code base, maybe that isn't so :(.

    I feel that I should point out for the record that you should never, 
ever let this happen. If your code doesn't always know which fd's that it 
might be interested in are or aren't valid, you have disasters waiting to 
happen. If you don't know for sure what an fd refers to, you have no 
business performing any operation on it. If it might have been closed, it 
also could now refer to something else entirely.

    DS


0
Reply David 11/21/2004 4:31:31 AM

"David Schwartz" <davids@webmaster.com> wrote in message news:cnp5nb$o34$1@nntp.webmaster.com...
:
: "James Antill" <james-netnews@and.org> wrote in message
: news:pan.2004.11.20.23.24.32.594604@and.org...
: > On Sat, 20 Nov 2004 22:36:38 +0000, Chris Markle wrote:
: >
: >> done without the associated cleanup, but may not find it. Until we do, we
: >> thought maybe if we "cleaned up" the fdset to rid it of closed files
: >> after
: >> we get this EBADF then maybe we could keep OpenLDAP running so the
: >> customer's 1.5million users stay happy. Not the best of circumstances but
: >> life's like that sometimes...
: >
: > The easiest thing to do here is switch to poll() or even epoll(), and
: > then trigger off which fd returns as bad.
: > It _should_ also be possible, with a small amount of work, to trace where
: > the fd that comes back as bad is coming from. Although from what I
: > remember of the Openldap code base, maybe that isn't so :(.
:
:     I feel that I should point out for the record that you should never,
: ever let this happen. If your code doesn't always know which fd's that it
: might be interested in are or aren't valid, you have disasters waiting to
: happen. If you don't know for sure what an fd refers to, you have no
: business performing any operation on it. If it might have been closed, it
: also could now refer to something else entirely.

Not entirely true.  Your process may inherit open fd's from a parent
process that has thoughtlessly not marked them close on exec.  If the
child process is persistent after the parent closes,  you may wind up
uselessly tying up a resource,  like a socket.  I had a problem with that
with Applixware years ago - the Applix license manager socket
would sometimes be left hanging.  When that happened,  you couldn't
start any new Applix sessions - disastrous with over 400 users over
a dozen international sites.  Worse,  the socket didn't show
up on a consistent file descriptor.  So I would simply close a range
of file descriptors above 2.  Originally I used fcntl to see which were
open,  then it dawned on me that closing a non-open fd didn't produce
any negative side affects.  It was actually quicker (though nanoscopically
so) to not check.

Dan Mercer

:
:     DS
:
:


0
Reply Dan 11/21/2004 5:28:01 PM

> Given an file descriptor that may or may not be open, what's the easiest and 
> cheapest (least cpu, etc.) way to tell if it's "good" (i.e. open)? Are there 
> other ways to do this?

One non portable solution (works under linux) can be a quick look at
/proc/pid/fd. Try this in your shell: ls /proc/$$/fd.

By the way, I was looking for documentations about processes that have
large numbers of open file descriptors. I guess such processes have to use
a define of a standard library constant to increase the size of fd_set. Is
this bound to any standard, or is it glibc-only ?

-- 
BBP

0
Reply Brieuc 11/23/2004 2:43:50 PM

Brieuc Jeunhomme <bbp@via.ecp.fr> writes:

>> Given an file descriptor that may or may not be open, what's the
>> easiest and cheapest (least cpu, etc.) way to tell if it's "good"
>> (i.e. open)? Are there other ways to do this?
>
> One non portable solution (works under linux) can be a quick look at
> /proc/pid/fd. Try this in your shell: ls /proc/$$/fd.
>
> By the way, I was looking for documentations about processes that have
> large numbers of open file descriptors. I guess such processes have to use
> a define of a standard library constant to increase the size of fd_set. Is
> this bound to any standard, or is it glibc-only ?

The maximum is defined by the kernel.  Calling select() with too high
a value will return EINVAL.  I once had to change it in my kernel, so
I could run a program built for Tru64 under Linux.  Apparently, Tru64
has a higher limit than a standard Linux kernel.

-- 
M�ns Rullg�rd
mru@inprovide.com
0
Reply iso 11/23/2004 2:59:07 PM

> The maximum is defined by the kernel.  Calling select() with too high
> a value will return EINVAL.  I once had to change it in my kernel, so
> I could run a program built for Tru64 under Linux.  Apparently, Tru64
> has a higher limit than a standard Linux kernel.

In fact, afaik, there are two limitations: one kernel limitation, and one
libc limitation. The kernel limit can be raised with some of course non
portable manipulation (a /proc hack for linux, I guess), but you also have
the problem that your standard library defines fd_set with a predefined
size. As FD_SET can not fail, the size of a fd_set must be determined at
compile time. In fact, if you look at glibc's implementation, a fd_set is
an array of integers whose size is such that you have one bit for each fd
you may have in a process, and glibc makes the assumption that the maximum
possible value of a file descriptor under linux is 1024.

But I was just wondering whether the limits can be raised in any portable
way.

-- 
BBP

0
Reply Brieuc 11/24/2004 2:08:23 PM

On Tue, 23 Nov 2004 15:59:07 +0100, Måns Rullgård wrote:

> The maximum is defined by the kernel.  Calling select() with too high
> a value will return EINVAL.  I once had to change it in my kernel, so
> I could run a program built for Tru64 under Linux.  Apparently, Tru64
> has a higher limit than a standard Linux kernel.

 As far as I know this has never been true, it's certainly not been true
since glibc. Using large values with select() does require using malloc()
and (fdset *) for dynamic allocation of storage, and IMO poll() is much
nicer ... but it is possible.

-- 
James Antill -- james@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

0
Reply James 11/24/2004 5:47:19 PM

James Antill <james-netnews@and.org> writes:

> On Tue, 23 Nov 2004 15:59:07 +0100, M�ns Rullg�rd wrote:
>
>> The maximum is defined by the kernel.  Calling select() with too high
>> a value will return EINVAL.  I once had to change it in my kernel, so
>> I could run a program built for Tru64 under Linux.  Apparently, Tru64
>> has a higher limit than a standard Linux kernel.
>
>  As far as I know this has never been true, it's certainly not been true
> since glibc. Using large values with select() does require using malloc()
> and (fdset *) for dynamic allocation of storage, and IMO poll() is much
> nicer ... but it is possible.

The program (I can't remember what it was) was linked against Tru64
libc, and didn't come anywhere near glibc.  The select() call was
returning something like EINVAL, and changing a #define in the kernel
made the program work exactly as intended.

-- 
M�ns Rullg�rd
mru@inprovide.com
0
Reply iso 11/24/2004 7:56:01 PM

16 Replies
331 Views

(page loaded in 0.176 seconds)

Similiar Articles:


















7/19/2012 3:22:32 PM


Reply: