coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] timeout: Ensure SIGCHLD signal is not blocked


From: Pádraig Brady
Subject: Re: [PATCH] timeout: Ensure SIGCHLD signal is not blocked
Date: Wed, 18 Oct 2017 20:12:55 -0700
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0

On 18/10/17 19:45, Pádraig Brady wrote:
> On 18/10/17 09:47, Thomas Jarosch wrote:
>> We inherit the signal mask from our parent process,
>> therefore ensure SIGCHLD is not blocked.
>>
>> If SIGCHLD is blocked, sigsuspend() won't be interrupted
>> when the child process exits and we hang until the timeout (SIGALRM).
>>
>> The issue has been found by an "autotest" testsuite
>> doing high level tests of a custom distribution.
>> One complex test case got stuck 100% of the time.
>>
>> This fixes a regression from
>>
>> commit 2f69dba5df8caaf9eda658c1808b1379e9949f22
>> Author: Tobias Stoeckmann <address@hidden>
>> Date:   Sun Feb 5 13:23:22 2017 +0100
>>
>>     timeout: fix race possibly terminating wrong process
>>
>>
>> Please CC: comments, I'm not subscribed to the list.
>>
>> Signed-off-by: Thomas Jarosch <address@hidden>
>> ---
>>  src/timeout.c | 24 ++++++++++++++----------
>>  1 file changed, 14 insertions(+), 10 deletions(-)
>>
>> diff --git a/src/timeout.c b/src/timeout.c
>> index a58b84f4e..aa2fff7d9 100644
>> --- a/src/timeout.c
>> +++ b/src/timeout.c
>> @@ -323,6 +323,16 @@ parse_duration (const char* str)
>>    return duration;
>>  }
>>  
>> +static void
>> +unblock_signal (int sig)
>> +{
>> +  sigset_t unblock_set;
>> +  sigemptyset (&unblock_set);
>> +  sigaddset (&unblock_set, sig);
>> +  if (sigprocmask (SIG_UNBLOCK, &unblock_set, NULL) != 0)
>> +    error (0, errno, _("warning: sigprocmask"));
>> +}
>> +
>>  static void
>>  install_sigchld (void)
>>  {
>> @@ -333,6 +343,10 @@ install_sigchld (void)
>>                                   more likely to work cleanly.  */
>>  
>>    sigaction (SIGCHLD, &sa, NULL);
>> +
>> +  /* we inherit the signal mask from our parent process,
>> +     ensure SIGCHLD is not blocked. */
>> +  unblock_signal(SIGCHLD);
>>  }
>>  
>>  static void
>> @@ -369,16 +383,6 @@ block_cleanup (int sigterm, sigset_t *old_set)
>>      error (0, errno, _("warning: sigprocmask"));
>>  }
>>  
>> -static void
>> -unblock_signal (int sig)
>> -{
>> -  sigset_t unblock_set;
>> -  sigemptyset (&unblock_set);
>> -  sigaddset (&unblock_set, sig);
>> -  if (sigprocmask (SIG_UNBLOCK, &unblock_set, NULL) != 0)
>> -    error (0, errno, _("warning: sigprocmask"));
>> -}
>> -
>>  /* Try to disable core dumps for this process.
>>     Return TRUE if successful, FALSE otherwise.  */
>>  static bool
>>
> 
> Drats, right thanks.
> 
> Isn't there also a small race if SIGCHLD is received
> after wait() returns but before the sigsuspend() runs?
> I.E. would this also be an appropriate addition to your patch:

On second thoughts there probably best as separate patchces
as they're separate issues really.
1. consistent hang with blocked SIGCHLD in parent
2. intermittent hang in all cases.

cheers,
Pádraig



reply via email to

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