Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Mar 2015 15:37:41 +0100
From:      Ivan Radovanovic <radovanovic@gmail.com>
To:        Jilles Tjoelker <jilles@stack.nl>
Cc:        freebsd-hackers@FreeBSD.org
Subject:   Re: kevent behavior
Message-ID:  <5512C835.7040207@gmail.com>
In-Reply-To: <20150324221541.GA67584@stack.nl>
References:  <550A6DA2.1070004@gmail.com> <20150324221541.GA67584@stack.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
On 03/24/2015 23:15, Jilles Tjoelker wrote:
> On Thu, Mar 19, 2015 at 07:33:06AM +0100, Ivan Radovanovic wrote:
>> Is there defined (and guaranteed) behavior of kevent if kqueue FD is
>> being closed while blocking kevent call is in progress?
>
>> Possible scenario would be like this:
>
>> Thread 1:
>> ...
>> kfd = kqueue();
>> ...
>> // create second thread afterwords
>> // and do blocking wait for events
>> result = kevent(kfd, changelist, nchanges, eventlist, nevents, NULL);
>> if (result == -1)
>> 	// check if there was request to stop listening for events
>
>> Thread 2:
>> // do something
>> // then close kqueue's fd
>> close(kfd);
>
>> I am asking this because file watcher implementation for mono is
>> implemented that way (which I find nicer than using timeout), but this
>> is apparently based on expected kevent behavior under Darwin, and I
>> can't find any mention that in FreeBSD kevent is going to behave the
>> same way (at least not on kqueue(2) manual page)
>
> This method is inherently unsafe, since you cannot be sure thread 1 has
> started blocking in kevent() when you close() in thread 2. If not, there
> might be a thread 3 creating a kqueue between thread 2's close and
> thread 1's kevent, and thread 1 will manipulate the new kqueue.
>
> Fortunately, EVFILT_USER provides an easy way to wake up a thread
> blocked in kevent().
>
> If kevent() was implemented as a cancellation point, pthread_cancel()
> would be another option, but it is not.
>

It is not really created in the same way as I put there, I just wanted 
to illustrate that we have 2 threads and that one is blocked in kevent 
and the other one is trying to close its kqueue descriptor.

I saw this EVFILT_USER thing, and it looked to me like it could be used 
to do much smarter unblocking of kevent but I believe manual page is 
relatively unclear there - what I do not understand is:

* how you trigger this user event (I would say with kevent if 
corresponding structure's NOTE_TRIGGER flag is set, but that doesn't 
sound logical since in my understanding kevent is basically like 
select(2) (ie call which checks if something happened without triggering 
things = call which reports about status change in system without 
causing change itself)?

* how does this work process-wise - is one ident restricted to process 
which created corresponding kqueue, or it is system wise (other process 
could trigger my kevent if same ident value is used)?



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5512C835.7040207>