Re: splice(-> FIFO) never wakes up inotify IN_MODIFY?

From: Ahelenia Ziemiańska
Date: Mon Jun 26 2023 - 11:15:31 EST


On Mon, Jun 26, 2023 at 05:00:01PM +0200, Jan Kara wrote:
> On Mon 26-06-23 16:25:41, Ahelenia Ziemiańska wrote:
> > On Mon, Jun 26, 2023 at 03:51:59PM +0200, Jan Kara wrote:
> > > On Mon 26-06-23 14:57:55, Ahelenia Ziemiańska wrote:
> > > > On Mon, Jun 26, 2023 at 02:19:42PM +0200, Ahelenia Ziemiańska wrote:
> > > > > > splice(2) differentiates three different cases:
> > > > > > if (ipipe && opipe) {
> > > > > > ...
> > > > > > if (ipipe) {
> > > > > > ...
> > > > > > if (opipe) {
> > > > > > ...
> > > > > >
> > > > > > IN_ACCESS will only be generated for non-pipe input
> > > > > > IN_MODIFY will only be generated for non-pipe output
> > > > > >
> > > > > > Similarly FAN_ACCESS_PERM fanotify permission events
> > > > > > will only be generated for non-pipe input.
> > > > Sorry, I must've misunderstood this as "splicing to a pipe generates
> > > > *ACCESS". Testing reveals this is not the case. So is it really true
> > > > that the only way to poll a pipe is a sleep()/read(O_NONBLOCK) loop?
> > > So why doesn't poll(3) work? AFAIK it should...
> > poll returns instantly with revents=POLLHUP for pipes that were closed
> > by the last writer.
> >
> > Thus, you're either in a hot loop or you have to explicitly detect this
> > and fall back to sleeping, which defeats the point of polling:
> I see. There are two ways around this:
>
> a) open the file descriptor with O_RDWR (so there's always at least one
> writer).
Not allowed in the general case, since you need to be able to tail -f
files you can't write to.

> b) when you get POLLHUP, just close the fd and open it again.
Not allowed semantically, since tail -f follows the file, not the name.

> In these cases poll(3) will behave as you need (tested)...
Alas, those are not applicable to the standard use-case.
If only linux exposed a way to see if a file was written to!

For reference with other implementations,
this just works and is guaranteed to work under kqueue(2) EVFILT_READ
(admittedly, kqueue(2) is an epoll(7)-style system and not an
inotify(7)-style one, but it solves the issue,
and that's what NetBSD tail -f uses).

Maybe this is short-sighted but I don't actually really see why inotify
is... expected? To only generate file-was-written events only for some
writes?

Attachment: signature.asc
Description: PGP signature