[PATCH/RFC future] nptl: reinstate SIGCANCEL/SIGSETXID safeguards

Kevin Cernekee cernekee at gmail.com
Sun May 8 16:25:24 UTC 2011


On Sun, May 8, 2011 at 8:19 AM, Peter Mazinger <ps.m at gmx.net> wrote:
>> libc sigfillset() returns a full set: all 128 bits are set.  libpthread
>> sigfillset() sets only 126 bits: everything except SIGCANCEL/SIGSETXID.
>>
>> libpthread sigprocmask() has extra code to prevent the caller from
>> blocking
>> SIGCANCEL/SIGSETXID.  libc sigprocmask() does not.
>
> If you did your tests on mips, couldn't it be, that this is influenced by the change of using kernel sigset_t size for mips on all "generic" syscall implementations (see KERNEL_SIGSET_T_SIZE macro)?

While the vector is sized differently on MIPS, I ran my test program
on an x86/glibc PC and saw that sigfillset() was still clearing the
bits for SIGCANCEL and SIGSETXID:

$ ./sigaction-test
Not masked: 3
Not masked: 32
Not masked: 33
sending SIGINT
sending SIGQUIT
caught sig 3

On the Linux PC, this behavior is seen regardless of whether
libpthread is linked in.

(Interestingly, on the PC, __sigaction() is duplicated in libc and
libpthread, but sigprocmask() and sigfillset() are not.)

After applying Austin's patch and my patch to uClibc 0.9.32-rc3, I was
able to verify that the sigfillset() behavior on the uClibc MIPS
target matches the behavior on the glibc PC.  This seems like it would
be a good thing.

Before applying my patch, SIGCANCEL and SIGSETXID were not defined so
the special libpthread behavior was not compiled into libc.  I do not
think there is a MIPS dependency involved.

I guess it probably would make sense to check the sigprocmask()
behavior at some point, as well.

Test program:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

void fn(int sig, siginfo_t *si, void *vctx)
{
	printf("caught sig %d\n", sig);
	exit(0);
}

int main(int argc, char **argv)
{
	sigset_t s, old;
	struct sigaction sa, sa_old;
	int i;

	sigfillset(&s);
	sigdelset(&s, SIGQUIT);
	sigprocmask(SIG_BLOCK, &s, &old);

	for (i = 1; i <= SIGRTMAX; i++)
		if (!sigismember(&s, i))
			printf("Not masked: %d\n", i);

	memset(&sa, 0, sizeof(sa));
	sa.sa_sigaction = fn;
	sa.sa_flags = SA_SIGINFO;
	sigaction(SIGQUIT, &sa, &sa_old);

	printf("sending SIGINT\n");
	usleep(100000);
	kill(0, SIGINT);
	usleep(100000);

	printf("sending SIGQUIT\n");
	usleep(100000);
	kill(0, SIGQUIT);
	usleep(100000);

	printf("failed to catch SIGQUIT\n");
	exit(1);
}


More information about the uClibc mailing list