> > 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

Reply via email to