Is it possible to block pending queued RealTime signals (AIO originating)?
David Xu
davidxu at freebsd.org
Wed Jan 9 02:06:31 UTC 2013
On 2013/01/09 07:14, Richard Sharpe wrote:
> On Tue, 2013-01-08 at 08:14 -0800, Richard Sharpe wrote:
>> On Tue, 2013-01-08 at 15:02 +0800, David Xu wrote:
>>> On 2013/01/08 14:33, Richard Sharpe wrote:
>>>> On Tue, 2013-01-08 at 10:46 +0800, David Xu wrote:
>>>>> On 2013/01/08 09:27, Richard Sharpe wrote:
>>>>>> Hi folks,
>>>>>>
>>>>>> I am running into a problem with AIO in Samba 3.6.x under FreeBSD 8.0
>>>>>> and I want to check if the assumptions made by the original coder are
>>>>>> correct.
>>>>>>
>>>>>> Essentially, the code queues a number of AIO requests (up to 100) and
>>>>>> specifies an RT signal to be sent upon completion with siginfo_t.
>>>>>>
>>>>>> These are placed into an array.
>>>>>>
>>>>>> The code assumes that when handling one of these signals, if it has
>>>>>> already received N such siginfo_t structures, it can BLOCK further
>>>>>> instances of the signal while these structures are drained by the main
>>>>>> code in Samba.
>>>>>>
>>>>>> However, my debugging suggests that if a bunch of signals have already
>>>>>> been queued, you cannot block those undelivered but already queued
>>>>>> signals.
>>>>>>
>>>>>> I am certain that they are all being delivered to the main thread and
>>>>>> that they keep coming despite the code trying to stop them at 64 (they
>>>>>> get all the way up to the 100 that were queued.)
>>>>>>
>>>>>> Can someone confirm whether I have this correct or not?
>>>>>>
>>>>>
>>>>> I am curious that how the code BLOCKs the signal in its signal handler ?
>>>>> AFAIK, after signal handler returned, original signal mask is restored,
>>>>> and re-enables the signal delivering, unless you change it in
>>>>> ucontext.uc_sigmask.
>>>>
>>>> It does try to block the signals in the signal handler using the
>>>> following code (in the signal handler):
>>>>
>>>> if (count+1 == TEVENT_SA_INFO_QUEUE_COUNT) {
>>>> /* we've filled the info array - block this signal until
>>>> these ones are delivered */
>>>> sigset_t set;
>>>> sigemptyset(&set);
>>>> sigaddset(&set, signum);
>>>> sigprocmask(SIG_BLOCK, &set, NULL);
>>>>
>>>> However, I also added pthread_sigmask with the same parameters to see if
>>>> that made any difference and it seemed not to.
>>>>
>>>
>>> This code won't work, as I said, after the signal handler returned,
>>> kernel will copy the signal mask contained in ucontext into kernel
>>> space, and use it in feature signal delivering.
>>>
>>> The code should be modified as following:
>>>
>>> void handler(int signum, siginfo_t *info, ucontext_t *uap)
>>> {
>>> ...
>>>
>>> if (count + 1 == TEVENT_SA_INFO_QUEUE_COUNT) {
>>> sigaddset(&uap->uc_sigmask, signum);
>>
>> Hmmm, this seems unlikely because the signal handler is operating in
>> user mode and has no access to kernel-mode variables.
>
> Well, it turns out that your suggestion was correct.
>
> I did some more searching and found another similar suggestion, so I
> gave it a whirl, and it works.
>
> Now, my problem is that Jeremy Allison thinks that it is a fugly hack.
> This means that I will probably have big problems getting a patch for
> this into Samba.
>
> I guess a couple of questions I have now are:
>
> 1. Is this the same for all versions of FreeBSD since Posix RT Signals
> were introduced?
>
I have checked source code, and found from FreeBSD 7.0, RT signal is
supported, and aio code uses signal queue.
> 2. Which (interpretation of which) combination of standards require such
> an approach?
>
>
The way I introduced is standard:
http://pubs.opengroup.org/onlinepubs/007904975/functions/sigaction.html
I quoted some text here:
When a signal is caught by a signal-catching function installed by
sigaction(), a new signal mask is calculated and installed for the
duration of the signal-catching function (or until a call to either
sigprocmask() or sigsuspend() is made). This mask is formed by taking
the union of the current signal mask and the value of the sa_mask for
the signal being delivered [XSI] [Option Start] unless SA_NODEFER or
SA_RESETHAND is set, [Option End] and then including the signal being
delivered. If and when the user's signal handler returns normally, the
original signal mask is restored.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
When the signal handler returns, the receiving thread resumes execution
at the point it was interrupted unless the signal handler makes other
arrangements. If longjmp() or _longjmp() is used to leave the signal
handler, then the signal mask must be explicitly restored.
This volume of IEEE Std 1003.1-2001 defines the third argument of a
signal handling function when SA_SIGINFO is set as a void * instead of a
ucontext_t *, but without requiring type checking. New applications
should explicitly cast the third argument of the signal handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
function to ucontext_t *.
^^^^^^^^^^^^^^^^^^^^^^^^^
---
The above means third parameter is pointing to ucontext_t which is used
to restored the previously interrupted context, the context contains
a signal mask which is also restored.
http://pubs.opengroup.org/onlinepubs/007904975/basedefs/ucontext.h.html
Regards,
David Xu
More information about the freebsd-hackers
mailing list