0

The man page for open() states for O_ASYNC:

This feature is available only for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs. See fcntl(2) for further details.

But I've used linux timers with epoll() successfully and setting O_ASYNC with fcntl() on a timer fd does not return an error. Obviously, no signals are being sent either. My question is, is it possible to get O_ASYNC working with linux timers? Are there any examples online? I know about the POSIX alternative, but was hoping to avoid it.

user1095108
  • 14,119
  • 9
  • 58
  • 116
  • O_ASYNC isn't for epoll – user253751 Mar 25 '22 at 17:28
  • yes, but `epoll()` works for socket fds, so in this sense a linux timer fd is kind of like a socket fd. – user1095108 Mar 25 '22 at 18:11
  • In fact probably nobody uses O_ASYNC any more. It's just a bad way to do things. Don't use it. – user253751 Mar 25 '22 at 23:05
  • I think it's still good to use with [coroutines](https://github.com/user1095108/cr) and some articles online say it can be more efficient than `(e)poll()/select()` sometimes. – user1095108 Mar 25 '22 at 23:51
  • O_ASYNC has nothing to do with the coroutine version of async. What do you think O_ASYNC does? – user253751 Mar 26 '22 at 18:23
  • `O_ASYNC` is AFAIK not standardized, so it could mean anything. But, under linux, it instructs the kernel to issue signals to the owner of a fd when certain events happen. I think you didn't even check the link I provided. – user1095108 Mar 26 '22 at 18:42
  • @user253751 why don't you just write a working example involving a linux timer and `O_ASYNC`? You obviously think I don't know much. Show me wisdom. – user1095108 Mar 26 '22 at 19:14
  • And you know that programming with signals is generally a bad idea? – user253751 Mar 27 '22 at 20:11
  • @user253751 nonsense, you need to tell that to someone else, a signal is like an interrupt to me and I've been dealing with those since the times of the z80. – user1095108 Mar 27 '22 at 22:04
  • yes, and they are the operating system's problem, and even the operating system does the minimal necessary work inside an interrupt and defers the rest until its main loop. Because interrupt programming is easy to get wrong. – user253751 Mar 27 '22 at 22:06
  • I am used to dealing with interrupts and love it when things go wrong. Really, the use of signals is not the problem here, but the OS is not issuing any, that's the problem. If you write a working example, you might be the first guy on the internet to do so. I've submitted a bug the linux bugzilla about this issue - I am 100% certain the bug is not on my side, no signals are being issued, period. – user1095108 Mar 27 '22 at 22:38
  • They will probably say either "write it yourself, nobody wants this feature" or "you're right, oops, it should return EINVAL" – user253751 Mar 28 '22 at 08:20
  • actually, it seems they will ignore the bug report altogether :) Their bugzilla seems dead. But the bug report exists and so does this question, so folks can save some time in the future. – user1095108 Mar 28 '22 at 17:17
  • With the way Linux works - you should feel free to fix it yourself and send a patch to the kernel mailing list. I am not familiar with that process so I'm not sure how to do that exactly. But I am 90% sure that nobody other than you actually cares about this bug, because O_ASYNC is not popular - so, if it is fixed, it will most likely be fixed by you. – user253751 Mar 28 '22 at 17:29
  • did you try also using F_SETOWN? https://stackoverflow.com/questions/12640993/how-to-use-o-async-and-fcntl-in-perl – user253751 Mar 28 '22 at 17:30
  • @user253751 yes, I did everything, just as if the linux timer fd were a socket fd. I tried treating them the same. As for fixing the bug, I am not enough of a linux enthusiast and the patch could be rejected anyway. – user1095108 Mar 28 '22 at 17:35
  • it is not an accept/reject thing, they will probably tell you why they don't like your patch and how to fix it so it will be accepted. I think if it fixes a real bug it will be accepted. It's just that I don't think anyone cares about O_ASYNC, and especially about O_ASYNC with timers. – user253751 Mar 28 '22 at 17:39
  • Did you know there's already a signal-based timer system? To send a signal after a certain amount of time, you can use ualarm (old), setitimer (also old) or timer_create (recommended). – user253751 Mar 28 '22 at 17:40
  • yes and I am using these POSIX timers and they work well, but I wanted to use linux timers. Why? Because using POSIX timers requires you to link with `librt` on some architectures and I wanted to avoid that. – user1095108 Mar 28 '22 at 18:15
  • and your proposed solution is to find something that is documented as not working and insist that it should work? – user253751 Mar 29 '22 at 21:43
  • it is not explicitly documented as not working and man pages are known to be out of sync with reality sometimes. There are many examples. An error should have been returned by fcntl() when trying to set O_ASYNC on a linux timer fd. That would have been definitive. – user1095108 Mar 30 '22 at 01:09

1 Answers1

1

We can see that F_SETFL calls setfl which calls a fasync function specific to the type of file.

By searching for fasync we can see how async support is implemented in many devices. Seems that it's not too complicated as mostly it only needs the device to store the async registration and send the signal (here is the fasync function implementation for this kind of file).

Going back to setfl we can notice that if the file type's fasync function is null, it just silently succeeds. This could be a bug, or it could be intentional. Let's assume it's a bug.

Now that the bug is in the kernel, there are probably programs relying on it, which would stop working if the bug was fixed. If a program did break and someone complained about it, the fix would get undone so the program would keep working, because Linus doesn't like to break programs. If it doesn't break any programs that actually exist (which is unlikely, in my opinion), it can be fixed.

Another option is to update the documentation.

Another option is to make it actually work.

My question is, is it possible to get O_ASYNC working with linux timers?

It's unlikely (but still possible) that any program is setting O_ASYNC on a timerfd since it doesn't work - so it's unlikely that it will break compatibility. And it looks like it's not terribly complicated to implement, based on the other examples. So, go ahead and write this patch and send it to the mailing list.

If you meant if it's possible to implement on today's kernels, without a patch, the answer is no, it is not. Here is the timerfd ops structure and there is no entry for fasync

Are there any examples online?

Yes, the examples are the source code for all the other kinds of files that support fasync.

user253751
  • 57,427
  • 7
  • 48
  • 90
  • +1 for actually doing some source diving. I won't submit a patch that would probably get rejected anyway, but I did submit a bug report. – user1095108 Mar 30 '22 at 13:08
  • @user1095108 as I said before, probably nobody actually cares about this bug and will fix it, except for you, so if you want it fixed, you'll probably have to do it – user253751 Mar 30 '22 at 13:27
  • I don't care that much, but if I find bugs, I usually make a bug report. – user1095108 Mar 30 '22 at 13:43