Re: Signal handling possibly wrong

From: Steven Rostedt
Date: Tue Aug 09 2005 - 15:03:59 EST


On Tue, 2005-08-09 at 21:41 +0200, Bodo Stroesser wrote:
> S
> > To me, the man pages make more sense, and I think the kernel is wrong.
>
> Yes, that's what I think, too. If someone doesn't want additional signals
> to be masked, he can set sa_mask to be empty.
> OTOH, I have no idea, what POSIX specifies. Maybe kernel is right and man
> page is wrong?
>
> Bodo
> >

Man pages and kernel are right. I just tested this out on 2.6.13-rc3
with the attached program and it seems to follow what is stated in the
man pages. So the assumption of what the code did by looking at it
proves to be the mistake. :-)

Conclusion: sa_mask defers the signals. SA_NODEFER defers the sent
signal.

-- Steve

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

void user1(int x)
{
int pid = getpid();
printf("pid[%d]: user1 start\n",pid);
sleep(5);
printf("pid[%d]: user1 stopped\n",pid);
}

void user2(int x)
{
int pid = getpid();
printf("pid[%d]:in user2\n",pid);
}

void intr(int x)
{
int pid = getpid();
printf("pid[%d]: received SIGINT\n",pid);
exit(0);
}

void start1(void)
{
struct sigaction act;

memset(&act,0,sizeof(act));

act.sa_handler = intr;
if ((sigaction(SIGINT,&act,NULL)) < 0) {
perror("child1: sigaction");
exit(-1);
}

act.sa_handler = user1;
sigaddset(&act.sa_mask,SIGUSR2);
if ((sigaction(SIGUSR1,&act,NULL)) < 0) {
perror("child1: sigaction");
exit(-1);
}

act.sa_handler = user2;
if ((sigaction(SIGUSR2,&act,NULL)) < 0) {
perror("child1: sigaction");
exit(-1);
}


for (;;)
;

}

void start2(void)
{
struct sigaction act;

memset(&act,0,sizeof(act));

act.sa_handler = intr;
if ((sigaction(SIGINT,&act,NULL)) < 0) {
perror("child2: sigaction");
exit(-1);
}

act.sa_handler = user1;
act.sa_flags |= SA_NODEFER;
if ((sigaction(SIGUSR1,&act,NULL)) < 0) {
perror("child2: sigaction");
exit(-1);
}

act.sa_handler = user2;
if ((sigaction(SIGUSR2,&act,NULL)) < 0) {
perror("child1: sigaction");
exit(-1);
}

for (;;)
;

}

int main(int argc, char **argv)
{
int pid[2];

if ((pid[0] = fork()) < 0) {
perror("fork");
} else if (!pid[0]) {
start1();
exit(0);
}

if ((pid[1] = fork()) < 0) {
perror("fork");
} else if (!pid[1]) {
start2();
exit(0);
}

printf("parent sending %d SIGUSR1\n",pid[0]);
kill(pid[0],SIGUSR1);
sleep(1);
printf("parent sending %d SIGUSR2\n",pid[0]);
kill(pid[0],SIGUSR2);
sleep(5);
printf("parent sending %d SIGUSR1\n",pid[0]);
kill(pid[0],SIGUSR1);
sleep(1);
printf("parent sending %d SIGUSR1\n",pid[0]);
kill(pid[0],SIGUSR1);
sleep(1);
printf("parent sending %d SIGINT\n",pid[0]);
kill(pid[0],SIGINT);

printf("parent sending %d SIGUSR1\n",pid[1]);
kill(pid[1],SIGUSR1);
sleep(1);
printf("parent sending %d SIGUSR2\n",pid[1]);
kill(pid[1],SIGUSR2);
sleep(5);
printf("parent sending %d SIGUSR1\n",pid[1]);
kill(pid[1],SIGUSR1);
sleep(1);
printf("parent sending %d SIGUSR1\n",pid[1]);
kill(pid[1],SIGUSR1);
sleep(1);
printf("parent sending %d SIGINT\n",pid[1]);
kill(pid[1],SIGINT);

exit(0);
}