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

Reply via email to