|
Home > Archive > Unix Programming > November 2004 > given an fd, how to tell if it's open?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
given an fd, how to tell if it's open?
|
|
| Chris Markle 2004-11-20, 5:49 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)? 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
| |
| DINH Viet Hoa 2004-11-20, 5:49 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
| |
| Måns Rullgård 2004-11-20, 5:49 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
| |
| DINH Viet Hoa 2004-11-20, 5:49 pm |
| Måns Rullgård wrote :
> "Chris Markle" <cmarkle@sendmail.com> writes:
>
>
> 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
| |
| Nick Landsberg 2004-11-20, 5:49 pm |
| M=E5ns Rullg=E5rd wrote:
> "Chris Markle" <cmarkle@sendmail.com> writes:
>=20
>=20
t and=20[vbcol=seagreen]
ied=20[vbcol=seagreen]
k=20[vbcol=seagreen]
e=20[vbcol=seagreen]
>=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
| |
| Måns Rullgård 2004-11-20, 5:49 pm |
| DINH Viet Hoa <dinh.viet.hoa@free.fr> writes:
> Måns Rullgård wrote :
>
>
> 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
| |
| David Schwartz 2004-11-20, 5:49 pm |
|
"DINH Viet Hoa" <dinh.viet.hoa@free.fr> wrote in message
news:etPan.419f8df5.47be063b.13fa@utopia...
> Måns Rullgård wrote :
>
>
> 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
| |
| Chris Markle 2004-11-20, 5:49 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
| |
| Nick Landsberg 2004-11-20, 5:49 pm |
| Chris Markle wrote:
> Nick,
>
>
>
>
> 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
| |
| James Antill 2004-11-20, 8:47 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/
| |
| David Schwartz 2004-11-21, 2:47 am |
|
"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:
>
>
> 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
| |
| Dan Mercer 2004-11-21, 5:49 pm |
|
"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
:
:
| |
| Brieuc Jeunhomme 2004-11-23, 8:27 am |
| > 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
| |
| Måns Rullgård 2004-11-23, 8:27 am |
| Brieuc Jeunhomme <bbp@via.ecp.fr> writes:
>
> 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
| |
| Brieuc Jeunhomme 2004-11-24, 8:12 am |
| > 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
| |
| James Antill 2004-11-24, 6:28 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/
| |
| Måns Rullgård 2004-11-24, 6:28 pm |
| James Antill <james-netnews@and.org> writes:
> On Tue, 23 Nov 2004 15:59:07 +0100, Måns Rullgård wrote:
>
>
> 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
|
|
|
|
|