Unix Programming - fclose memory fault

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > January 2004 > fclose memory fault





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 fclose memory fault
Jeff

2004-01-23, 5:35 pm

I am using fdopen to associate a FILE with a socket descriptor. My
problem is this: if the socket is closed and I pass the FILE returned
from fdopen to fclose, my program dies with a memory fault.

My question: why do I get a memory fault with fclose when the socket
descriptor is closed and how can I prevent that?

TIA,
Jeff

DINH Viet Hoa

2004-01-23, 5:35 pm

Jeff wrote :
quote:

> I am using fdopen to associate a FILE with a socket descriptor. My
> problem is this: if the socket is closed and I pass the FILE returned
> from fdopen to fclose, my program dies with a memory fault.
>
> My question: why do I get a memory fault with fclose when the socket
> descriptor is closed and how can I prevent that?



could you show us a minimal code so that we can point you on the error ?
fclose() should not make your program fails even if the stream is opened
with fdopen().

--
DINH V. Hoa,

etPan! - newsreader, mail user agent -- http://libetpan.sf.net/etpan

Rich Teer

2004-01-23, 5:35 pm

On Mon, 12 Jan 2004, Jeff wrote:
quote:

> I am using fdopen to associate a FILE with a socket descriptor. My
> problem is this: if the socket is closed and I pass the FILE returned
> from fdopen to fclose, my program dies with a memory fault.
>
> My question: why do I get a memory fault with fclose when the socket
> descriptor is closed and how can I prevent that?



Don't close the socket; let fclose() do it. (Or perhaps clearer:
don't mix the standard I/O library with sockets.)

--
Rich Teer, SCNA, SCSA

President,
Rite Online Inc.

Voice: +1 (250) 979-1638
URL: http://www.rite-online.net
Andrei Voropaev

2004-01-23, 5:35 pm

On 2004-01-12, Rich Teer <rich.teer@rite-group.com> wrote:
quote:

> On Mon, 12 Jan 2004, Jeff wrote:
>
>
> Don't close the socket; let fclose() do it. (Or perhaps clearer:
> don't mix the standard I/O library with sockets.)
>



Good recommendation. But still, check your program for buffer overflows,
double free or any other type of memory corruption. Usually, when you see
that library functions cause segfault then either you are passing bad
arguments, or corrupting memory somewhere in your code.

Andrei
Loic Domaigne

2004-01-23, 5:35 pm

Hi!
quote:

> could you show us a minimal code so that we can point you on the error ?
> fclose() should not make your program fails even if the stream is opened
> with fdopen().



I would also expect the behavior explained by Dinh. However, I checked what
SUSv3 is saying about that issue:

</copy-paste>

The fclose() function shall fail if:

[EBADF]
[CX] [Option Start] The file descriptor underlying stream is not valid.
[Option End]

</copy-paste>


This is a CX-extension, i.e. the 2001 revised version of the classical
Posix 1003.1. Your system might not necessarily supports this
"quite recent" standard.

quote:

[QUOTE][color=darkred]
> Don't close the socket; let fclose() do it. (Or perhaps clearer:
> don't mix the standard I/O library with sockets.)



Yes. IMHO, that's a good practical advise (may still, alas, hold a few
years)


Regards,
Loic.

--
Article posté via l'accès Usenet http://www.mes-news.com
Accès par Nnrp ou Web
Geoff Clare

2004-01-23, 5:35 pm

"Loic Domaigne" <loic-dev@gmx.net> wrote, on Tue, 13 Jan 2004:
quote:

> I checked what SUSv3 is saying about that issue:
>
> </copy-paste>
>
> The fclose() function shall fail if:
>
> [EBADF]
> [CX] [Option Start] The file descriptor underlying stream is not
> valid.
> [Option End]
>
> </copy-paste>
>
>
> This is a CX-extension, i.e. the 2001 revised version of the classical
> Posix 1003.1. Your system might not necessarily supports this "quite
> recent" standard.



CX marks extensions to the C Standard, not extensions to the old POSIX.1.
(Perhaps you are confusing it with EX which was used in SUSv1 and SUSv2
to mark UNIX extensions to POSIX.1).

The original POSIX.1 required fclose() to set errno to EBADF *if* it
returned an error indication when the underlying fd was invalid. This
meant that if there was any data in the buffer that needed flushing,
fclose() would have to fail with EBADF, but if there was no data to
flush then implementations could choose whether to have fclose() fail
with EBADF or successfully close the stream. The only difference in
the new POSIX.1/SUSv3 is that returning an error indication in the
second case is mandatory instead of optional.

--
Geoff Clare <nospam@gclare.org.uk>
Loic Domaigne

2004-01-23, 5:35 pm

Hello Geoff,
quote:

[QUOTE][color=darkred]
> CX marks extensions to the C Standard, not extensions to the old POSIX.1.
> (Perhaps you are confusing it with EX which was used in SUSv1 and SUSv2
> to mark UNIX extensions to POSIX.1).



No, actually I'm still learning SUSv3 and I try hard to become a seasonned
SUSler :^)

I think, I got it where my mistake was. Taken from the explanations
about [CX]:

<copy-paster>
[CX] Extension to the ISO C standard
The functionality described is an extension to the ISO C standard.
Application writers may make use of an extension as it is supported on all
IEEE Std 1003.1-2001-conforming systems.
</copy-paste>

it occurred to me that ISO C in question would be the ISO C99 and, yes,
I then messed up with the reference to Posix 1003.1-2001. (This § doesn't
say that it is an extension devised by Posix 1003.1-2001, but that system
conforming to that standard supports automatically [CX]).

So you would say that - modulo Jeff's code corectness - Jeff's platform
doesn't conform?


Thanks Geoff for your -as usual- sharp insights
Loic.
--
Article posté via l'accès Usenet http://www.mes-news.com
Accès par Nnrp ou Web
Geoff Clare

2004-01-23, 5:35 pm

"Loic Domaigne" <loic-dev@gmx.net> wrote, on Tue, 13 Jan 2004 21:58:05
+0000:
quote:

> So you would say that - modulo Jeff's code corectness - Jeff's platform
> doesn't conform?



Yes. It doesn't even conform to the C Standard - assuming Jeff's code
has not done something that results in undefined behaviour - since the
C Standard requires fclose() either to return 0 or to return EOF, and
on Jeff's system the call in question does neither.

--
Geoff Clare <nospam@gclare.org.uk>
Eric Sosman

2004-01-23, 5:35 pm

Geoff Clare wrote:
quote:

>
> "Loic Domaigne" <loic-dev@gmx.net> wrote, on Tue, 13 Jan 2004 21:58:05
> +0000:
>
>
> Yes. It doesn't even conform to the C Standard - assuming Jeff's code
> has not done something that results in undefined behaviour - since the
> C Standard requires fclose() either to return 0 or to return EOF, and
> on Jeff's system the call in question does neither.



I don't think so. Jeff has somehow closed the socket
"out from beneath" the associated FILE* descriptor. In the
C Standard there is no way at all to do this, hence the
program has already departed from the Standard's guarantees.

How about this one:

FILE *stream = (FILE*) "Hello, world!";
fclose (stream);

Clearly, fclose() is not required to do anything sensible
in a case like this -- and I think Jeff's case is similar
in spirit.

--
Eric.Sosman@sun.com
Casper H.S. Dik

2004-01-23, 5:36 pm

Geoff Clare <geoff@clare.See-My-Signature.invalid> writes:
quote:

>"Loic Domaigne" <loic-dev@gmx.net> wrote, on Tue, 13 Jan 2004 21:58:05
>+0000:


quote:

[QUOTE][color=darkred]
>Yes. It doesn't even conform to the C Standard - assuming Jeff's code
>has not done something that results in undefined behaviour - since the
>C Standard requires fclose() either to return 0 or to return EOF, and
>on Jeff's system the call in question does neither.



If you pass it a valid FILE *; if you don't pass it a valid
FILE *, you get "undefined behaviour".

SEGV is completely acceptable as an implementation
of "undefined behaviour".

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
Geoff Clare

2004-01-23, 5:36 pm

I wrote, on Thu, 15 Jan 2004:42:11 +0000:
quote:

>
> Yes. It doesn't even conform to the C Standard - assuming Jeff's code
> has not done something that results in undefined behaviour - since the C
> Standard requires fclose() either to return 0 or to return EOF, and on
> Jeff's system the call in question does neither.



Seeing Eric and Casper's comments, I realise I should have qualified
that statement rather than using a misleading shortcut. What I meant
is that it doesn't conform to the requirements from the C Standard that
POSIX.1 places on implementations by reference to the C Standard.
(For POSIX.1-1990 this really was just "by reference". For POSIX.1-2001
the text from the C Standard appears in POSIX.1 (with extensions), but
it is still kind of "by reference" since POSIX.1-2001 defers to the
C Standard if there are any conflicts in the text.)
Eric Sosman

2004-01-23, 5:36 pm

Geoff Clare wrote:
quote:

>
> I wrote, on Thu, 15 Jan 2004:42:11 +0000:
>
>
> Seeing Eric and Casper's comments, I realise I should have qualified
> that statement rather than using a misleading shortcut. What I meant
> is that it doesn't conform to the requirements from the C Standard that
> POSIX.1 places on implementations by reference to the C Standard.
> (For POSIX.1-1990 this really was just "by reference". For POSIX.1-2001
> the text from the C Standard appears in POSIX.1 (with extensions), but
> it is still kind of "by reference" since POSIX.1-2001 defers to the
> C Standard if there are any conflicts in the text.)



I'm not sure the qualification clears things up -- at
least, it doesn't clear them up for me! For a less outrageous
example, consider

FILE *stream = fopen(...); /* assume success */
fclose (stream); /* must behave nicely */
fclose (stream); /* can be nice or naughty */

Clearly, the second fclose() can cause unrestricted mischief:
it need not return a value of 0 or EOF, and it need not return
at all! The problem is that although `stream' is a FILE*, it
is no longer a *valid* FILE* -- and the invalidity of the
argument voids all guarantees of "nice" behavior.

The O.P. did something perhaps a little less obviously bad,
but still managed to make his FILE* invalid by invalidating
the file descriptor used by the underlying machinery:

int fd = socket(...); /* assume success */
FILE *stream = fdopen(fd,...); /* assume success */
close (fd); /* must be nice */
fclose (stream); /* nice or naughty */

Once again, the FILE* has become invalid -- this time, by a
different route, but invalid nonetheless. Pass an invalid
argument to fclose(), and all bets are off. In particular,
no conclusions about the conformity or non-conformity of the
implementation can be drawn based on its behavior after the
invalid fclose() call; anything goes.

--
Eric.Sosman@sun.com
Geoff Clare

2004-01-23, 5:36 pm

"Eric Sosman" <Eric.Sosman@sun.com> wrote, on Fri, 16 Jan 2004:
quote:

>
> I'm not sure the qualification clears things up -- at
> least, it doesn't clear them up for me! For a less outrageous example,
> consider
>
> FILE *stream = fopen(...); /* assume success */ fclose (stream);
> /* must behave nicely */ fclose (stream); /* can be nice
> or naughty */
>
> Clearly, the second fclose() can cause unrestricted mischief: it need
> not return a value of 0 or EOF, and it need not return at all! The
> problem is that although `stream' is a FILE*, it is no longer a *valid*
> FILE* -- and the invalidity of the argument voids all guarantees of
> "nice" behavior.



Agreed, this is use of an invalid stream and the behaviour is undefined.
quote:

> The O.P. did something perhaps a little less obviously bad,
> but still managed to make his FILE* invalid by invalidating the file
> descriptor used by the underlying machinery:
>
> int fd = socket(...); /* assume success */
> FILE *stream = fdopen(fd,...); /* assume success */
> close (fd); /* must be nice */
> fclose (stream); /* nice or naughty */
>
> Once again, the FILE* has become invalid -- this time, by a different
> route, but invalid nonetheless.



No. There is nothing in POSIX to suggest that closing fileno(stream)
makes stream invalid. In fact, for POSIX.1-2001 quite the opposite is
true - it clearly requires fclose() to return EOF and set errno to EBADF
when the fd underlying the stream is invalid.

--
Geoff Clare <nospam@gclare.org.uk>
Loic Domaigne

2004-01-23, 5:36 pm

Hi,
quote:

> No. There is nothing in POSIX to suggest that closing fileno(stream)
> makes stream invalid. In fact, for POSIX.1-2001 quite the opposite is
> true - it clearly requires fclose() to return EOF and set errno to EBADF
> when the fd underlying the stream is invalid.



Hope I didn't shortcut too much, but it occurs to me it is what I
tried to convey in my original post :-\ Namely that the OP-case is
"well-defined" by Posix.1-2001, but that no all platform might support
that standard, even today.

( Ok, wasn't so clear, because I messed up the description of [CX] ).

BTW, we have a simular issue when closing a fd from a thread, where
another thread might be using APIs referring to that fd. Refer to
poll() discussion on austin-group.

Cheers,
Loic.
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com