[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: timeout: heads up: kFreeBSD's timers cause all timeout tests to hang
From: |
Pádraig Brady |
Subject: |
Re: timeout: heads up: kFreeBSD's timers cause all timeout tests to hang |
Date: |
Wed, 21 Sep 2011 15:36:47 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:6.0) Gecko/20110816 Thunderbird/6.0 |
On 09/20/2011 09:47 AM, Pádraig Brady wrote:
> On 09/19/2011 12:48 PM, Jim Meyering wrote:
>> While working around the getcwd limitation on kFreeBSD,
>> I noticed that all timeout-using tests were hanging.
>> HAVE_TIMER_SETTIME was defined, so I confirmed that
>> disabling that definition made it so all tests now pass:
>>
>> diff --git a/src/timeout.c b/src/timeout.c
>> index d734e4e..c87d603 100644
>> --- a/src/timeout.c
>> +++ b/src/timeout.c
>> @@ -112,7 +112,7 @@ settimeout (double duration)
>> deprecated by POSIX. Instead we fallback to single second
>> resolution provided by alarm(). */
>>
>> -#if HAVE_TIMER_SETTIME
>> +#if 0
>> struct timespec ts = dtotimespec (duration);
>> struct itimerspec its = { {0, 0}, ts };
>> timer_t timerid;
>>
>> Obviously the above is just FYI.
>> The real change should probably be in configure-time code that tests
>> not just for existence, but also for working timer functions.
>
> It's not that simple unfortunately.
> What's happening there is that glibc is emulating
> these timer functions using an implicitly created thread
> (on any non Linux >= 2.6 kernel).
>
> So when timeout::cleanup() gets the SIGALRM
> and then does kill(0, SIGTERM), _two_ signals
> are sent, which causes it to go into a loop
> sending signals. (So do a `killall -9 timeout`
> on any kfreebsd systems you experienced the hang on.)
>
> Interestingly FreeBSD 8.2 has these timer functions
> implemented in the kernel, so perhaps GNU/kFreeBSD debian 8.1
> just needs better wiring up with glibc?
>
> In any case we should handle this, but I'm unsure how to proceed.
> This would work around it:
>
> diff --git a/src/timeout.c b/src/timeout.c
> index d734e4e..de7faad 100644
> --- a/src/timeout.c
> +++ b/src/timeout.c
> @@ -146,6 +146,7 @@ settimeout (double duration)
> static int
> send_sig (int where, int sig)
> {
> + signal (sig, SIG_IGN);
> sigs_to_ignore[sig] = 1;
> return kill (where, sig);
> }
>
> But I'm worried about blocking signals we send indefinitely,
> so I think we'll need another approach.
I can't think of anything better,
so attached is a full patch for the above method.
I'd prefer to avoid timer_settime() if it creates a thread,
but I don't know how to portably detect the presence of multiple threads.
An alternative to ignore signals we send to our own group is
attach a marker to the signal with sigqueue() and we
could then discard all such signals. But that functionality
is missing on many platforms and would complicate things anyway.
cheers,
Pádraig.
timeout-threads.diff
Description: Text document