coreutils
[Top][All Lists]
Advanced

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

Attachment: timeout-threads.diff
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]