From looking at the man page, it look like epoll does not return the file descriptor of the event; it returns a union containing user-defined data, although one of the union's fields is called "fd" because it is presumably intended to be used as the file descriptor.
However, this is still subject to the problems you mention, as well as that you presumably can no longer control events for a file descriptor if you do longer have it, so it is still seems a problem.
Putting the file descriptor in the "struct epoll_event" instead of "epoll_data_t" would have avoided the problem of events on the wrong file descriptor, but that still might not be good enough. (It could specify -1 as the file descriptor for events of file descriptors that you do not have access to.)
Some of this is just the problem with POSIX in general. I did consider such problems (of file descriptors and of event handling) in my own ideas of operating system design, which uses capabilities. I would want to avoid the mess that other systems is doing, too. A capability in this case is fundamentally a different data type than numbers (and IPC treats them differently), although I am not sure yet how to handle this in a suitable way within a process (tagged memory might do, although not all computers use tagged memory). (Note that most I/O is done using IPC and not by system calls; the number of system calls is limited and is usually only used for managing the capabilities and event handling. This would also improve security as well as other things.)
> From looking at the man page, it look like epoll does not return the file descriptor of the event; it returns a union containing user-defined data, although one of the union's fields is called "fd" because it is presumably intended to be used as the file descriptor.
Yes -- so how do you unregister an event after you close the file, or dup the file descriptor? You have no way to do that, you just keep getting events for a resource you no longer have open, so long as the parent or child still has it open!
It's incredible that you can set things up in a way that you get events on a resource you can no longer refer to in any way.
> so how do you unregister an event after you close the file ... You have no way to do that, you just keep getting events for a resource you no longer have open ... It's incredible that you can set things up in a way that you get events on a resource you can no longer refer to in any way.
Yes, I thought that too, it does not make much sense to me either. (I would suppose that you could close the epoll file descriptor, but then that would cancel all events, and not only that one.)
It's you again! Hi. We talked about capabilities a while back.
> I am not sure yet how to handle this in a suitable way within a process
If this is about implementing capabilities, I think partitioned capabilities should be the default.
> Some of this is just the problem with POSIX in general. I did consider such problems (of file descriptors and of event handling)
Yes, I think the kernel is trying to do too much. The more micro/exokernel it is, the better, IMO. Doesn't reduce (essential) complexity, but gives programmers the flexibility to tackle it how they want.
I'm also curious how you're thinking of doing event handling in general, like D-Bus or something. I think IPC is best left as a point-to-point bare bones communication channel, but even then it's pretty complex as the central load-bearing construct. For events, I expect there would be a lot of shared memory usage. It would use centralized services and/or userspace-defined capabilities to restrict who can receive certain events. I'm not too concerned since it's more of a userspace concern, unlike IPC.
> If this is about implementing capabilities, I think partitioned capabilities should be the default.
I am not entirely sure, but probably.
> I'm also curious how you're thinking of doing event handling in general, like D-Bus or something. I think IPC is best left as a point-to-point bare bones communication channel, but even then it's pretty complex as the central load-bearing construct.
I dislike D-Bus. My idea does not use any kind of shared message bus.
IPC would be done as messages; any process that has a reference to a capability can send messages to that capability and can request to receive messages from that capability; so these received messages can be events. The message can contain any bytes and also capabilities. The system calls would be used to request and send such events, with parameters for blocking/non-blocking, for multiple objects at once, and for atomic wait-and-send or wait-and-receive (in order to avoid some types of race conditions).
> For events, I expect there would be a lot of shared memory usage.
I had also thought of shared memory, although my intention is to allow network transparency and proxy capabilities (although network transparency would be implemented by using proxy capabilities), so I had thought to not use shared memory.
However, shared memory may be useful, but there may be ways to allow it to work transparently without otherwise affecting the protocol, e.g. with read-only mapping and copy-on-write mapping, or for a mapping to only be accessible by receiving events. A pass-through function would also be possible, to make some proxies more efficient. These features are essentially optimizations which can be optional to implement, so if you implement a proxy that does not use them, the programs will still work even if they are unaware that it uses a proxy that is unable to share memory.
There is then also other considerations such as audio/video/input synchronization; if you display a movie (or a game, which will involve input as well) then the audio/video would be synchronized, even if one or both are being redirected (e.g. you might redirect the audio output to a EQ filter or to a remote computer, or you might redirect both together to a remote computer or recorder, or to a program that expects input from a camera).
> It would use centralized services and/or userspace-defined capabilities to restrict who can receive certain events. I'm not too concerned since it's more of a userspace concern, unlike IPC.
Who can receive certain events would be a feature of the userspace-defined capabilities. Some services can be centralized, that many programs will be capable of using, either directly or through proxies; these proxies would be used for handling security and many other features.
Some of my ideas are similar (but different in many ways) like some other designs, including a few things listed in http://www.divergent-desktop.org/blog/2020/08/10/principles-... Proxy capabilities, and the Command, Automation, and Query Language, and the common data format used for most data, and other features of the system that I intended to have, will be able to help with some of the things listed there, as well as other benefits. (My ideas are actually mostly independent of that and other documents, but some of them end up being similar to those, and sometimes my ideas can then be refined when I learn more from such documents, too.)
However, this is still subject to the problems you mention, as well as that you presumably can no longer control events for a file descriptor if you do longer have it, so it is still seems a problem.
Putting the file descriptor in the "struct epoll_event" instead of "epoll_data_t" would have avoided the problem of events on the wrong file descriptor, but that still might not be good enough. (It could specify -1 as the file descriptor for events of file descriptors that you do not have access to.)
Some of this is just the problem with POSIX in general. I did consider such problems (of file descriptors and of event handling) in my own ideas of operating system design, which uses capabilities. I would want to avoid the mess that other systems is doing, too. A capability in this case is fundamentally a different data type than numbers (and IPC treats them differently), although I am not sure yet how to handle this in a suitable way within a process (tagged memory might do, although not all computers use tagged memory). (Note that most I/O is done using IPC and not by system calls; the number of system calls is limited and is usually only used for managing the capabilities and event handling. This would also improve security as well as other things.)