bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Plea for clarification on bz #12724


From: Eric Blake
Subject: Re: Plea for clarification on bz #12724
Date: Thu, 28 Jul 2011 07:30:40 -0600
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.18) Gecko/20110621 Fedora/3.1.11-1.fc14 Lightning/1.0b3pre Mnenhy/0.8.3 Thunderbird/3.1.11

On 07/28/2011 02:00 AM, Csaba Henk wrote:
- However, it seems to me that the cited part of the standard
   is not sufficient to make a judgement regarding which
   of glibc 2.14 and Solaris is the standard compliant.

   There is a more fundamental semantic difference here.

   Let us modify the test code by adding some printfs:

diff -up ftestx.c ftesty.c
--- ftestx.c    2011-07-28 10:17:23.001229687 +0300
+++ ftesty.c    2011-07-28 10:01:53.106267361 +0300
@@ -29,7 +29,9 @@ main (void)
    assert (0<= fd2);
    f = fdopen (fd2, "w");
    assert (f);
+  printf("%ld\n", ftell(f));

So far, so good. fdopen() is required to set the stream position to the same as the underlying fd position, so this should always print 1.

    assert(lseek(fd, 4, SEEK_SET) == 4);
+  printf("%ld\n", ftell(f));

Undefined behavior.  POSIX states:

The result of function calls involving any one handle (the "active handle") is 
defined elsewhere in this volume of POSIX.1-2008, but if two or more handles are used, 
and any one of them is a stream, the application shall ensure that their actions are 
coordinated as described below. If this is not done, the result is undefined.

A handle which is a stream is considered to be closed when either an fclose() 
or freopen() is executed on it (the result of freopen() is a new stream, which 
cannot be a handle on the same open file description as its previous value), or 
when the process owning that stream terminates with exit(), abort(), or due to 
a signal. A file descriptor is closed by close(), _exit(), or the exec 
functions when FD_CLOEXEC is set on that file descriptor.

For a handle to become the active handle, the application shall ensure that the 
actions below are performed between the last use of the handle (the current 
active handle) and the first use of the second handle (the future active 
handle). The second handle then becomes the active handle. All activity by the 
application affecting the file offset on the first handle shall be suspended 
until it again becomes the active file handle. (If a stream function has as an 
underlying function one that affects the file offset, the stream function shall 
be considered to affect the file offset.)
...
For the second handle:

    *

      If any previous active handle has been used by a function that explicitly 
changed the file offset, except as required above for the first handle, the 
application shall perform an lseek() or fseek() (as appropriate to the type of 
handle) to an appropriate location.

http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_05

Your code has two handles (fd and f), you are starting with fd as the active handle and did a reposition, then switched to an action on f. However, on f, you did ftell() without first doing fseek() - therefore, you triggered undefined behavior. So glibc's printing of 1 (the stream position does not always reflect the underlying fd position) and Solaris' printing of 4 (ftell consults the underlying fd) are both permissible, as is any other number of behaviors.

    assert (fclose (f) == 0);

The POSIX wording for fclose() effectively requires an fflush(), and since fflush() is one of the functions that resync's the stream position back to the fd position as modified by the first handle, before making f the active handle, I still stand by my analysis that at this point in the program, the offset of the file description should remain at 4, and not be reset to 1 (that is, since the transition from the first handle which set the offset to 4 to the second handle which used fclose() is clean, the action on the second handle must not corrupt the fd position back to 1 merely because the FILE* position had not been advanced from 1). Solaris behavior is correct, glibc behavior is buggy.


   Thus the problem boils down to: what is correct, let a file
   offset change imply an implicit change in the file position, or not?

When dealing with multiple handles to a file description, then you must ensure that you can properly transition from one active handle to another. As long as the active handle transition rules are defined, then yes, a file offset change will be observable as an implicit change in the file position. As soon as the active handle transition rules are broken (such as calling ftell() without an intervening fflush()), then behavior is undefined.

--
Eric Blake   address@hidden    +1-801-349-2682
Libvirt virtualization library http://libvirt.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]