static void sig_init() { sigset_t blksig; sigemptyset(&blksig); sigaddset(&blksig, SIGINT); sigaddset(&blksig, SIGTERM); sigaddset(&blksig, SIGPIPE); Pthread_sigmask(SIG_BLOCK, &blksig, NULL); }
// from kevent(2) on FreeBSD 6.4: // EVFILT_SIGNAL Takes the signal number to monitor as the identifier and // returns when the given signal is delivered to the process. // This coexists with the signal() and sigaction() facili- // ties, and has a lower precedence. The filter will record // all attempts to deliver a signal to a process, even if the // signal has been marked as SIG_IGN. Event notification // happens after normal signal delivery processing. data // returns the number of times the signal has occurred since // the last call to kevent(). This filter automatically sets // the EV_CLEAR flag internally. // from signalfd(2) on Linux 2.6.31: // The mask argument specifies the set of signals that the caller wishes // to accept via the file descriptor. This argument is a signal set whose // contents can be initialized using the macros described in sigsetops(3). // Normally, the set of signals to be received via the file descriptor // should be blocked using sigprocmask(2), to prevent the signals being // handled according to their default dispositions. It is not possible to // receive SIGKILL or SIGSTOP signals via a signalfd file descriptor; // these signals are silently ignored if specified in mask. static inline int add_signal_event(evhandler *eh,struct evectors *ev,int sig, evcbfxn rfxn,void *cbstate){ sigset_t mask,oldmask; sigemptyset(&mask); if(Sigaddset(&mask,sig)){ return -1; } // FIXME actually we want to set the procmask of evhandler threads // present and future...not necessarily the entire process. hrmmmm... if(Pthread_sigmask(SIG_BLOCK,&mask,&oldmask)){ return -1; } if(!sigismember(&oldmask,sig)){ nag("Warning: signal %d was unblocked prior to entrance\n",sig); } #ifdef LIB_COMPAT_LINUX { // FIXME we could restrict this all to a single signalfd, since // it takes a sigset_t...less potential parallelism, though int fd; if((fd = Signalfd(-1,&mask,SFD_NONBLOCK | SFD_CLOEXEC)) < 0){ return -1; } if(add_fd_to_evcore(eh,ev,fd,signalfd_demultiplexer,NULL,eh)){ Close(fd); return -1; } } #else #ifdef LIB_COMPAT_FREEBSD { struct kevent k; EV_SET(&k,sig,EVFILT_SIGNAL,EV_ADD | EV_CLEAR,0,0,NULL); if(add_evector_kevents(ev,&k,1)){ return -1; } } #else #error "No signal event implementation on this OS" #endif #endif setup_evsource(eh->sigarray,sig,rfxn,NULL,cbstate); return 0; }
int main(int argc, char **argv) { int n, e; unsigned prod_sum, cons_sum; struct thread_data *data; pthread_attr_t attr; int canceled = 0; pthread_t tid; if (argc > 1 && !strcmp("-", argv[1])) Error("usage: %s num_producers num_consumers " "num_items maxbuflen busy-loops", argv[0]); if (argc > 1) { num_producers = atoi(argv[1]); if (num_producers < 0) num_producers = 1; if (num_producers > MAXPRODUCERS) num_producers = MAXPRODUCERS; } if (argc > 2) { num_consumers = atoi(argv[2]); if (num_consumers < 0) num_consumers = 1; if (num_consumers > MAXCONSUMERS) num_consumers = MAXCONSUMERS; } if (argc > 3) { num_items = atoi(argv[3]); if (num_items < 0) num_items = 0; } if (argc > 4) { maxbuflen = atoi(argv[4]); if (maxbuflen < 0) maxbuflen = 1; if (maxbuflen > MAXBUFLEN) maxbuflen = MAXBUFLEN; } if (argc > 5) busy_loops = atoi(argv[5]); printf("num_producers %d num_consumers %d num_items %d " "maxbuflen %d busy-loops %d\n", num_producers, num_consumers, num_items, maxbuflen, busy_loops); num_items /= num_producers; /* items/producer */ sigemptyset(&sigmask); sigaddset(&sigmask, SIGINT); Pthread_sigmask(SIG_BLOCK, &sigmask, NULL); Pthread_attr_init(&attr); Pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); /* Starte die Producer */ for (n = 0; n < num_producers; ++n) { data = malloc(sizeof(struct thread_data)); if (!data) Error("malloc"); data->seed = n; data->no = n; producer_data[n] = data; Pthread_create(&producers[n], &attr, Producer, data); } /* Starte die Consumer */ for (n = 0; n < num_consumers; ++n) { data = malloc(sizeof(struct thread_data)); if (!data) Error("malloc"); data->no = n; Pthread_create(&consumers[n], &attr, Consumer, data); } Pthread_create(&tid, &attr, SigThread, NULL); /* Warte auf alle Producer */ prod_sum = 0; for (n = 0; n < num_producers; ++n) { Pthread_join(producers[n], (void **)&data); if (data == PTHREAD_CANCELED) canceled = 1; prod_sum += producer_data[n]->sum; } if (canceled) printf("*** program was cancelled\n"); /* setze eof und wecke consumer auf */ Pthread_mutex_lock(&buf_mutex); eof = 1; Pthread_mutex_unlock(&buf_mutex); Pthread_cond_broadcast(&empty_cond); /* Warte auf alle Consumer */ cons_sum = 0; for (n = 0; n < num_consumers; ++n) { Pthread_join(consumers[n], (void **)&data); cons_sum += data->sum; } printf("prot_sum %u cons_sum %u\n", prod_sum, cons_sum); if (cons_sum != prod_sum) printf("ERROR\n"); return 0; }