2013/01/08(火)sigprocmaskの検証

Linux実装は pthread*のマスクと sigprocmask()とは同じって書いてた。。
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>

#define gettid() syscall(SYS_gettid)

// 0: sigprocmask at process, 1:thr1, 
#define DF_CHGMASK_ID 2
//#define DF_USE_PTHREADMASK
//#define DF_INITIAL_MASK (SIGSEGV)
//#define DF_INITIAL_MASK (SIGABRT)
#define DF_INITIAL_MASK (12)


void abt_handler(int n, siginfo_t *pSigInf, void *pContext)
{
struct sigaction sa;

	printf("I am dead...[%d][parent:%d][tid=%d][thread_id=%ld]", getpid(), getppid(), gettid(), (long)pthread_self());
	memset(&sa,0,sizeof(struct sigaction));
//_exit(1);
	sigemptyset(&sa.sa_mask);
//	sa.sa_flags |= SA_SIGINFO ;
	sa.sa_handler = SIG_DFL;
//	sigaction(SIGABRT,&sa,NULL);
//	raise(SIGABRT);
}

void register_handler()
{
struct sigaction sa;

	memset(&sa,0,sizeof(struct sigaction));
	sigemptyset(&sa.sa_mask);
	sa.sa_flags |= SA_SIGINFO ;
	sa.sa_sigaction = abt_handler;
//	sigaction(SIGABRT,&sa,NULL);
	sigaction( 12,&sa,NULL);
}


struct st_signals_st {
	int signo;
	const char *pcSignal ;
	} st_signals[] = {
			{SIGHUP,    "SIGHUP"},
			{SIGINT,    "SIGINT"},
			{SIGQUIT,   "SIGQUIT"},
			{SIGILL,    "SIGILL"},
			{SIGTRAP,   "SIGTRAP"},
			{SIGABRT,   "SIGABRT"},
			{SIGIOT,    "SIGIOT"},
			{SIGBUS,    "SIGBUS"},
			{SIGFPE,    "SIGFPE"},
			{SIGKILL,   "SIGKILL"},
			{SIGUSR1,   "SIGUSR1"},
			{SIGSEGV,   "SIGSEGV"},
			{SIGUSR2,   "SIGUSR2"},
			{SIGPIPE,   "SIGPIPE"},
			{SIGALRM,   "SIGALRM"},
			{SIGTERM,   "SIGTERM"},
			{SIGSTKFLT, "SIGSTKFLT"},
			{SIGCHLD,   "SIGCHLD"},
			{SIGCONT,   "SIGCONT"},
			{SIGSTOP,   "SIGSTOP"},
			{SIGTSTP,   "SIGTSTP"},
			{SIGTTIN,   "SIGTTIN"},
			{SIGTTOU,   "SIGTTOU"},
			{SIGURG,    "SIGURG"},
			{SIGXCPU,   "SIGXCPU"},
			{SIGXFSZ,   "SIGXFSZ"},
			{SIGVTALRM, "SIGVTALRM"},
			{SIGPROF,   "SIGPROF"},
			{SIGWINCH,  "SIGWINCH"},
			{SIGIO,     "SIGIO"},
			{SIGPOLL,   "SIGPOLL"},
			{SIGPWR,    "SIGPWR"},
			{SIGSYS,    "SIGSYS"},
			{0, NULL}
		} ;

void dump_sigmask(const char* pMsg, sigset_t* sig_mask)
{
struct st_signals_st* pStSignal = st_signals ;
int i;
	puts(pMsg);
	while( pStSignal->pcSignal ){
		if (sigismember( sig_mask, pStSignal->signo )) {
			putchar('1');
		}
		else {
			putchar('0');
		}
		pStSignal++;
	}
	putchar('_');
	for (i=SIGRTMIN; i<=SIGRTMAX; i++) {
		if (sigismember( sig_mask, i )) {
			putchar('1');
		}
		else {
			putchar('0');
		}
	}
	puts("");
return ;
}


void* thr1(void* arg)
{
sigset_t sig_mask ;

	sleep(1);
printf("[%d/ppid=%d/tid=%d/self=%ld] wakeup thr1!\n", getpid(), getppid(), gettid(), (long)pthread_self());
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr1", &sig_mask);

#if (DF_CHGMASK_ID==1)
	sigfillset(&sig_mask);
#ifdef DF_USE_PTHREADMASK
	if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) {
#else
	if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) {
#endif
		perror ("main(): failure set...");
	}
#endif
	sleep(4);
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr1", &sig_mask);

#if (DF_CHGMASK_ID==1)
	sigemptyset(&sig_mask);
#ifdef DF_USE_PTHREADMASK
	if (pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) {
#else
	if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) {
#endif
		perror ("main(): failure set...");
	}
#endif
	sleep(4);
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr1", &sig_mask);
	sleep(10);
}

void* thr2(void* arg)
{
sigset_t sig_mask ;

	register_handler();
//	sigaddset(&sig_mask, DF_INITIAL_MASK) ;

	sigemptyset(&sig_mask);
	sigaddset(&sig_mask, 12) ;
#ifdef DF_USE_PTHREADMASK
	if (pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) {
#else
	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) {
#endif
		perror ("thr2(): Dead set...");
	}


	sleep(2);
printf("[%d/ppid=%d/tid=%d/self=%ld] wakeup thr2!\n", getpid(), getppid(), gettid(), (long)pthread_self());
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr2", &sig_mask);

	sleep(4);
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr2", &sig_mask);

	sleep(4);
	pthread_sigmask(SIG_UNBLOCK, NULL, &sig_mask);
	dump_sigmask("thr2", &sig_mask);

	system("echo thr2 is spawn $$ ; sleep 17");

	sleep(3);
}



int
main(int argc, char *argv[])
{
int status=0;
int fd;
pthread_t child[2];
sigset_t sig_mask ;

	sigfillset(&sig_mask);
	if (sigprocmask(SIG_BLOCK, &sig_mask, NULL)) {
		perror ("main(): Dead set...");
	}
/*
	sigaddset(&sig_mask, DF_INITIAL_MASK) ;
	if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) {
		perror ("main(): Dead set...");
	}
*/
//	register_handler();

	if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) {
		perror ("main(): Dead get...");
	}
	dump_sigmask("main", &sig_mask);



/* スレッド生成 */
	pthread_create(&child[0], NULL, thr1, NULL );
	pthread_create(&child[1], NULL, thr2, NULL );

	sleep(4);	

#if (DF_CHGMASK_ID==0)
	sigemptyset(&sig_mask);
	if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) {
		perror ("main(): failure set...");
	}
#endif
	if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) {
		perror ("main(): Dead get...");
	}
	dump_sigmask("main", &sig_mask);

	sleep(4);	

#if (DF_CHGMASK_ID==0)
	sigfillset(&sig_mask);
	if (sigprocmask(SIG_SETMASK, &sig_mask, NULL)) {
		perror ("main(): failure set...");
	}
#endif
	if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) {
		perror ("main(): Dead get...");
	}
	dump_sigmask("main", &sig_mask);

	sleep(4);	
	if (sigprocmask(SIG_UNBLOCK, NULL, &sig_mask)) {
		perror ("main(): Dead get...");
	}
	dump_sigmask("main", &sig_mask);

	status = pthread_join(child[0], NULL);
	if (status<0) {
		printf("pthread_join(0) returns: %d\n", status);
	}
	status = pthread_join(child[1], NULL);
	if (status<0) {
		printf("pthread_join(0) returns: %d\n", status);
	}
return 0;
}