Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is creating two FILEs for the same file descriptor well-defined?

POSIX specifies an fdopen function that creates a FILE for a file descriptor. POSIX also specifies a fileno function that returns the file descriptor for a FILE. Together, these two could be used to create a second FILE accessing the same underlying file descriptor as an existing file:

FILE *secondfile(FILE *f, const char *mode)
{
    int fd = fileno(f);

    return fd >= 0 ? fdopen(fd, mode) : NULL;
}

Is this a well-defined operation under POSIX? What happens when I access both the original FILE and the second FILE I made for the same file descriptor? Is the interaction specified? If yes, how?

Historically, Unices used a fixed table of FILE structures for the 20 files you could open. Calling fdopen() on a file descriptor that has already been associated with a FILE would thus corrupt the existing file and yield undefined behaviour. I am not sure if such an implementation of stdio is still allowed by POSIX, which is why I am asking this question.

like image 939
fuz Avatar asked Nov 16 '15 12:11

fuz


People also ask

Can two file descriptors point to the same file?

One process can have multiple file descriptors point to the same entry (e.g., as a result of a call to dup() ) Multiple processes (e.g., a parent and child) can have file descriptors that point to the same entry.

Are file descriptors unique for each process?

File descriptors are generally unique to each process, but they can be shared by child processes created with a fork subroutine or copied by the fcntl, dup, and dup2 subroutines.

How many file descriptors can a process have?

Hard Limits The hard limit of a resource is the maximum value that a user can increase their soft limit to. Thus, we know that this system's hard limit for the number of open file descriptors is 4096.

Do Threads share the same file descriptors?

Threads in the same process share an address space and file descriptor table, so we do not need to save the page-table root pointer or the fd table.


2 Answers

POSIX explicitly permits multiple "handles" to be associated simultaneously with the same underlying "open file description", where handles can be either file descriptors or streams. Although it does not specifically address multiple streams opened via fdopen() on the same file descriptor, I see no reason to suppose that these would be subject to more or different requirements than any two streams associated with the same open file description are generally subject to.

POSIX defines constraints on how two handles on the same open file description may be used in order to avoid undefined behavior. It is relevant here that those constraints are few indeed for handles that are file descriptors; almost all of them apply to streams, and they are organized mainly around conditions related to buffering. The exceptions are related to positioning.

If you use your streams in a manner consistent with those constraints -- mostly, but not exclusively, by ensuring that output is not buffered unwritten in one stream when you switch to using the other -- you can expect the stream I/O functions to behave as documented. Otherwise, the behavior is explicitly undefined.

like image 83
John Bollinger Avatar answered Sep 21 '22 07:09

John Bollinger


Given a typical Unix implementation, with a FILE data structure containing a file descriptor to read from, and a buffer for, eh, buffering, and if you know the size of the buffer, and the policy for filling it (when the data is needed, not immediately when the buffer is empty), I would say that you can determine what will happen. But I don't know what the POSIX standard says, and I do know that it will be a difficult thing to use in a program. ("Ok, so I've read the first 4096 bytes from the file on disk into this FILE, and the next 4096 bytes into that FILE, and the third 4096-byte chunk from the file will be read into the FILE that reaches the end of its buffer first and needs to read more...")

(I've never done anything like this deliberately, but I seem to remember such symptoms from debugging code that got FILEs and file descriptors mixed up.)

My guess would be that POSIX doesn't specify this well enough that it will be guaranteed to work. For example, does POSIX specify when a buffer inside a FILE will be filled by reading from the file descriptor? When empty, when empty and more data is needed, or either of these, depending on something? Depending on choice there, data from the file descriptor will show up in different FILEs.

like image 22
Thomas Padron-McCarthy Avatar answered Sep 20 '22 07:09

Thomas Padron-McCarthy