I am looking for a way to check the current number of file descriptors being monitored by an epoll instance. I use the following for creating and populating the epoll instance
epoll_create
epoll_ctl
Platform is Gnu/Linux.
As far as I know, there is no system call available which can provide the count of file descriptors which are getting monitored by epoll. You can achieve this by maintaining one counter variable. Increment/decrement this variable after successfully adding/removing the file descriptor to the epoll using epoll_ctl().
Related
I just debugged a program that did roughly:
pthread_create(...);
close(0);
int t = open("/named_pipe");
assert(t == 0);
Occasionally it fails, as pthread_create actually briefly opens file descriptors on the new thread – specifically /sys/devices/system/cpu/online – which if you're unlucky occur between the close and open above, making t something other than 0.
What's the safest way to do this? What if anything is guaranteed about pthread_create regarding file descriptors? Am I guaranteed that if there are 3 file descriptors open before I call pthread_create, then there'll also be 3 open when it's returned and control has been passed to my function on the new thread?
In multi-threaded programs, you need to use dup2 or dup3 to replace file descriptors. The old trick with immediate reuse after close no longer works because other threads and create file descriptors at any time. Such file descriptors can even be created (and closed) implicitly by glibc because many kernel interfaces use file descriptors.
dup2 is the standard interface. Linux also has dup3, with which you can atomically create the file descriptor with the O_CLOEXEC flag set. Otherwise, there would still be a race condition, and the descriptor could leak to a subprocess if the process ever forks and executes a new program.
I need to open multiple TCP sockets, corresponding to each namespace programmed in linux.
I wanted to know whether the fd assigned to these sockets might be the same or they are always system-wide unique?
A given process can only be a member of one namespace. A file descriptor is only relevant within the context of one process.
If one process creates several sockets, those file descriptors are known only to that process, and are not useful to outside processes (apart from diagnostic tools like /proc/PID/fd).
If you have sockets created in two different namespaces, then by definition they are created in two different processes and therefore the file descriptors need not be (and likely will not be) unique.
If you want something globally unique, you might be interested in the socket "inodes." You can read about how to list those here: How do I find the inode of a TCP socket? . I suspect, but haven't verified, that those inode numbers would be unique on a machine, regardless of namespace.
I've heard that file descriptors are unique to each process. But, are they unique to the entire system? How are they handled within the kernel? If file descriptors are not unique system-wide, how does a system call, like read, write, close, etc, know what process the file descriptor they receive belong to?
Invoking a system call does not involve a change of PID; the system call simply looks at the FD table of the current PID.
The operating system simply has to maintain a mapping of the combination of process ID and file descriptor to identify a particular file. It might do so by maintaining a list of file descriptors with a given process's task control block, or by whatever other means the implementer decided to use.
But, are they unique to the entire system?
No, they are unique to a process.
A typical kernel has access to a data structure representing the process when a system call is made. A file descriptor can be as simple as an index into an array in that data structure.
I'm working on a multithreaded application where multiple threads may want exclusive access to the same file. I'm looking for a way of serializing these operations. I was planning to use flock, lockf, or fcntl locking. However it appears that with these methods an attempt to lock a file by a second thread when a first thread already owns the lock will be granted, because the two threads are in the same process. This is according to the manpages for flock and fnctl (and I guess in linux lockf is implemented with fnctl). Also supported by this other question. So, are there other ways of locking a file in linux which works at a thread-level instead of a process-level?
Some alternatives that I came up with which I do not like are:
1) Use a lockfile (xxx.lock) opened with O_CREAT | O_EXCL flags. This call will succeed only in one thread if there is contention. The problem with this is that then other threads have to spin on the call until they achieve the lock, meaning that I have to _yield() or sleep() which makes me think this is not a great option.
2) Keep a mutex'ed list of all open files. When a thread wants to open/close a file it has to lock the list first. When opening a file, it searches the list to see if it's open. This sounds particularly inefficient because it requires a significant amount of work even if the file is not owned yet.
Are there other ways of doing this?
Edit:
I just discovered this text in my system's manpages which isn't in the online man pages:
If a process uses open(2) (or similar) to obtain more than one descriptor for the same file, these descriptors are treated independently by flock(). An attempt to lock the file using one of these file descriptors may be denied by a lock that the calling process has already placed via another descriptor.
I'm not happy about the words "may be denied", I'd prefer "will be denied" but I guess it's time to test that.
I wanted to use inotify for monitoring some files in my C program.
I am wondering if it is safe to have one thread reading from inotify descriptor (the one returned by inotify_init) thus blocking until some event happens, during this waiting there would be a possibility of adding new file to watch queue using inotify_add_watch during the other thread waiting period.
Do I need to synchronize those actions or is it safe to do such thing?
Don't have the exact answer, but I do know from experience that you can't even open files in another thread without triggering the read() in the thread you are using inotify. I recall reading that you need to use inotify_init1() along with the IN_CLOEXEC flag to allow file io in other threads. I'm not sure if that means you can actually use inotify in more than one thread simultaneously though.