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