> > I was able to reproduce watching for new data and truncation of the > > file using "kqueue" but I do not quite understand how the original tail > > watches when the file appears again after deletion or renaming. I am sorry that I could not be clear enough in my words above. I meant I already understood a little how "kqueue" magic works. And I replicated some event watching logic in my learning task. I see how file truncating, deleting and renaming is watched by waiting NOTE_DELETE, NOTE_RENAME and NOTE_TRUNCATE events in EVFILT_VNODE filter. But I still do not see where and what event is watched for to make sure the file with initial file name is back (e.g. after deletion). After deleting a file there is no initial file descriptor, so there is nothing to watch using the old EVFILT_VNODE filter. I also see that after NOTE_DELETE | NOTE_RENAME events are caught only tfreopen function is called and I do not see any event watching actions in that function.
So my primary question might be: how can I monitor file creation (using events) by only knowing its name? On Fri Feb 17 11:47:03 2023, Mike Fischer wrote: > > > Am 17.02.2023 um 06:23 schrieb Maksim Rodin <a23s4a2...@yandex.ru>: > > > > Hello, > > Sorry if I chose the wrong place to ask such a question. > > I have been learning C for a couple of months and along with reading > > "C Primer Plus" by Stephen Prata and doing some exercises from it I took > > a hard (for me) task to replicate a tail program in its simplest form. > > I was able to reproduce watching for new data and truncation of the > > file using kqueue but I do not quite understand how the original tail > > watches when the file appears again after deletion or renaming. > > By reading the original tail sources downloaded from OpenBSD mirror I > > see that this is done by calling tfreopen function which seems to use a > > "for" loop to (continuously?) stat(2) the file name till stat(2) > > successfully > > returns and it does not seem to load a CPU as a simple continuous "for" > > loop would do. > > No, the for loop in line 362 of forward.c > (https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/tail/forward.c?annotate=1.33) > iterates over the files. Note that tail allows you to monitor more than one > file at a time, see tail(1). > > > > Can someone explain how it is done? > > tfreopen is called in line 224 of the same file inside a while(1) loop. At > the top of this loop kevent is called (L191). See kevent(2) for details on > how that works. That is the real _magic_ here ;-) > > tfqueue sets up the event mechanism for a single file so you may want to look > at that as well. > > > > May be there is a better way to watch for the file to appear correctly? > > The way tail(1) does this seems pretty optimal to me. > > > > Is inserting a sleep(3) in a loop an appropriate way? > > You could do this, but it’s less optimal than using kqueue/kevent because > sleep(3) will wait longer than necessary in some cases and wake up sooner > than required in others. It is basically a way to do polling which is always > worse than event driven code. > > > > > > Below is the function how it is done in tail: > > It would have been better to cite the file name and line numbers, very easy > with https://cvsweb.openbsd.org as I did above. There is also a mirror of the > repo on Github, which also makes this sort of thing very easy: > https://github.com/openbsd. E.g.: > https://github.com/openbsd/src/blob/master/usr.bin/tail/forward.c#L224 > > The links to the repositories are right on the https://www.openbsd.org home > page, so not hard to find at all. > > > HTH > Mike > > PS. Note that I am not an expert on kqueue/kevent programming. So followups > for details on these functions would probably need to be answered by someone > else. -- Maksim Rodin