When I create a socket using accept() and make a FILE out of it using fdopen(), what do I have to do to clean everything up? Do I need to do fclose() on the FILE, shutdown() and close() on the socket, or only the shutdown() and or close() or fclose()? If I don't do fclose(), do I have to free() the FILE pointer manually?
From man fdopen:
The file descriptor is not dup’ed, and will be closed when the stream created by fdopen() is closed
So I would just use fclose(), which also closes the underlying file descriptor. I don't know whether shutdown() is needed, either.
From http://opengroup.org/onlinepubs/007908775/xsh/fclose.html
The fclose() function will perform a
close() on the file descriptor that is
associated with the stream pointed to
by stream.
If you've wrapped your socket in a stream it probably no longer makes sense to shutdown(), at least not without flushing the stream first. But I won't swear to that, because I don't know that there are no uses where you'd want to shutdown() rather than just close().
You have 2 things here you need to clean up: the stream represented by FILE and the file descriptor represented by the socket. You need to close the stream first, then the file descriptor. So, in general you will need to fclose() any FILE objects, then close() any file descriptors.
Personally I have never used shutdown() when I want to cleanup after myself, so I can't say.
edit
Others have correctly pointed out that fdclose() will also close the underlying file descriptor, and since calling close() on a close file descriptor will lead to an error, in this case you only need fdclose().
Related
I am opening another process in my application using popen and parsing its output. I want to get notified as soon as the program has made any output. Currently all stuff in my program uses epoll for such actions. Now popen does return me a FILE * instead of a fd. Is it save to use the fileno function and put the resulting fd into epoll? If not, is there another way? I do not want the process to block, thats why I want the notifications.
Yes it is safe, as long as you don't do any extra thing with the file descriptor without being careful it seems to be safe. One more thing, is that you probably want to mark the file descriptor as non-blocking too. So that you can read() without blocking and handle EBUSY or EAGAIN checking errno.
I am reading in a blocked way from a device/filedescriptor.
It might happen, that in a different thread the device is closed and filedescriptor is deleted. Unfortunatly the read doesn't return or take notice and keeps blocking.
As a workaround I could do a while loop with select as a timeout. If a timeout happens, I can check the filedescriptor and in case it is gone not calling read but return.
I am wondering, if there is a better way in Linux-C ?
The code you are describing has an inherent race condition - if another thread could be a in blocking read() on a file descriptor when you close() that file descriptor, the other thread could just as well be just about to call read() instead.
You can't call close() unless you know that all other threads are no longer in a position to be using that file descriptor at all.
The easiest way to handle cases like you describe is for one thread to be the 'owning' thread of each file descriptor, that is responsible for closing the file descriptor. Other threads don't directly close it - instead they mark the file descriptor as "to be closed" in some shared data structure and wake up the owning thread.
You can make it possible to wake the owning thread by having it not block in read() but instead block in select() or poll() with another file descriptor - usually a pipe - in the set as well as the target file descriptor. The thread is woken by writing to the other end of that pipe.
Once a file descriptor is closed by other thread, it's not easy to verify it happened. What if other thread re-opened a file and got the same
file descriptor? On a successful close() call, you can't access the file descriptor again and it'll be undefined. On a failed close() call, POSIX leaves the state of the file descriptor unspecified.
The select() option suffers from the same as described above.
Your problem is not really anything different to any other data race issue in a multi-threaded program. I suggest you re-write the
code so that threads don't access the file descriptor without synchronization. Or, avoid multiple threads reading from the same file descriptor if that's possible.
If I fopen a file, what's the difference between calling fclose or close and which one should I use?
If forked children have access to the file as well, what should they do when they are finished with the file?
fclose() is function related with file streams. When you open file with the help of fopen() and assign stream to FILE *ptr. Then you will use fclose() to close the opened file.
close() is a function related with file descriptors. When you open file with the help of open() and assign descriptor to int fd. Then you will use close() to close the opened file.
The functions like fopen(), fclose() etc are C standard functions, while the other category of open(), close() etc are POSIX-specific. This means that code written with open(), close() etc is not a standard C code and hence non-portable. Whereas the code written with fopen(), fclose etc is a standard code and can be ported on any type of system.
which one should I use?
It depends on how you opened the file. If you open a file with fopen(), you should use fclose() and if you open file with open(), you should use close().
If forked children have access to the file as well, what should they do when they are finished with the file?
This is also dependent on where you made the fork() call: before opening the file or after opening it.
See: Are file descriptors shared when fork()ing?
See: man fclose and man close
open() and close() are UNIX syscalls which return and take file descriptors, for use with other UNIX syscalls such as write(). fopen() and fclose() are standard C library functions which operate on FILE*s, for use with things like fwrite and fprintf. The latter are almost always what you should be using: They're simpler and more cross-platform.
As for your second question, forked children have the same numeric file descriptor as the parent, but it's a copy; they can close it, and it will still be open for the parent and other children. (Though personally, I don't like to have files open when I fork()... I like to make that sort of shared resource usage explicit. Pipes, of course, are an exception.)
which one should I use?
If you open a file with fopen, close it with fclose. Using close in this case may cause a memory leak on a handle allocated by fopen
I would like to use splice to zero-copy data from STDIN_FILENO to a file descriptor (which could be to a regular file, char or block device, FIFO, or anything that can be opened with open). In order to use splice, either the from file descriptor or to file descriptor must be the appropriate end of a pipe, so generally a pipe is created to serve as an intermediary buffer when the programmer wants to zero-copy data from non-pipe to non-pipe. However, if STDIN_FILENO is already the read end of a pipe, then I could skip that step and attempt to splice directly from STDIN_FILENO to the other file descriptor. Therefore, I would like to be able to determine whether STDIN_FILENO is the read end of a pipe.
Is there a Linux system call that can determine whether STDIN_FILENO is the read end of a pipe?
To get information about an open fd, you can use fstat(). I'd guess that st_mode of the result should be S_IFIFO for a pipe. Alternatively, /proc/self/fd/ and /proc/self/fdinfo/ also provide some information about a file descriptor. Keep in mind that /proc is linux-specific.
However, I think it might be easier to just try to use splice() first and if it fails (with EINVAL?) fall back to your magic.
As an alternative, lseek() will fail with ESPIPE if "fd is associated with a pipe, socket, or FIFO." So a no-op lseek(fd, 0, SEEK_CUR) will tell you if the file descriptor is any of these.
In my situation, this covers all of the cases I was interested in.
By using fdopen(), fileno() it's possible to open streams with existing file descriptors. However the proper way to close a file, once you've opened it with a stream is to fclose() the FILE pointer. How can one close the stream, but retain the open file descriptor?
This behaviour is akin to calling fflush() and then fileno(), and then never using the FILE pointer again, except in closing. An additional concern is that if you then fdopen() again, there are now multiple FILE pointers, and you can only close one of them.
If you're on a POSIXy system (which I assume you are, since you have fileno()), you can use dup() to clone the file descriptor:
int newfd = dup(fileno(stream));
fclose(stream);
Or you can hand fdopen() a duplicate file descriptor:
FILE *stream = fdopen(dup(fd), "r");
Either way, the other copy of the fd won't close with the FILE *. However, keep in mind the location pointer is shared, so be careful if you are using both at the same time. Also, any fcntl() locks held on the original fd will be released when you close the copy.
If everything else fails, dup(2) could help.