Re: [PATCH v2 5/6] signal: sys_sigprocmask() needsretarget_shared_pending()

From: Oleg Nesterov
Date: Wed Apr 27 2011 - 08:58:20 EST


On 04/26, Linus Torvalds wrote:
>
> > + sigemptyset(&new_full_set);
> > + if (how == SIG_SETMASK)
> > + new_full_set = current->blocked;
> > + new_full_set.sig[0] = new_set;
>
> Ugh. This is just ugly.

Agreed.

> Could we not instead turn the whole thing into a "clear these bits"
> and "set these bits", and get rid of the "how" entirely for the helper
> function?
>
> IOW, we'd have
>
> switch (how) {
> case SIG_BLOCK:
> clear_bits = 0;
> set_bits = new_set;
> break;
> case SIG_UNBLOCK:
> clear_bits = new_set;
> set_bits = 0;
> break
> case SIG_SET:
> clear_bits = low_bits;
> set_bits = new_set;
> break;
> default:
> return -EINVAL;
> }
>
> and notice how you now can do that helper function *WITHOUT* any
> conditionals, and just make it do
>
> sigprocmask(&clear, &set, NULL);
>
> which handles all cases correctly (just "andn clear" + "or set") with
> no if's or switch'es.
>
> This is why I _detest_ that idiotic "sigprocmask()" interface.

Agreed, but...

Yes, sigprocmask(how) is ugly, but there are sys_rt_sigprocmask() and
sys_sigprocmask() which have to handle these SIG_* operations anyway.
So, I think we should do:

1. Almost all callers of sigprocmask() use SIG_SETMASK, we can
simply change them to use set_current_blocked().

2. Add the new helper (probably like you suggested) and convert
other 9 callers.

3. Unexport sigprocmask() and remove the last "*oldset" argument,
it should be only used by sys_*sigprocmask() syscalls.

But firstly I'd like to finish this "don't change ->blocked directly"
conversion. And this patch changes sys_sigprocmask() so that it looks
similar to sys_rt_sigprocmask().

What do you think?

If you can't accept sys_sigprocmask()->sigprocmask(), will you agree
with

SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
old_sigset_t __user *, oset)
{
old_sigset_t old_set, new_set;
sigset_t new_blocked;

old_set = current->blocked.sig[0];

if (nset) {
if (copy_from_user(&new_set, nset, sizeof(*nset)))
return -EFAULT;
new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));

new_blocked = current->blocked;

switch (how) {
case SIG_BLOCK:
sigaddsetmask(&new_blocked, new_set);
break;
case SIG_UNBLOCK:
sigdelsetmask(&new_blocked, new_set);
break;
case SIG_SETMASK:
new_blocked.sig[0] = new_set;
break;
default:
return -EINVAL;
}

set_current_blocked(&new_blocked);
}

if (oset) {
if (copy_to_user(oset, &old_set, sizeof(*oset)))
return -EFAULT;
}

return 0;
}
?

Oleg.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/