#include #include #include #include #include #include #include #include #include static int handler_run; static const union sigval my_sigval = { .sival_int = 42, }; static const char msgbuf[] = "hello"; #define bail(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0); static void handler(int sig, siginfo_t *si, void *notused) { assert(si->si_code == SI_MESGQ); assert(si->si_ptr == my_sigval.sival_ptr); /* Succeeds */ assert(si->si_int == my_sigval.sival_int); /* Succeeds */ /* This should run only once */ assert(handler_run == 0); handler_run++; } int main(int argc, char *argv[]) { struct signalfd_siginfo fdsi; struct sigaction newact; struct sigevent sev; struct mq_attr attr; sigset_t mask; size_t msglen; char *rcvbuf; mqd_t mqdes; ssize_t s; int sfd; if (argc != 2) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } newact.sa_flags = SA_SIGINFO | SA_RESETHAND; newact.sa_sigaction = handler; sigemptyset(&newact.sa_mask); if (sigaction(SIGRTMIN, &newact, NULL) == -1) bail("sigaction"); mqdes = mq_unlink(argv[1]); if (mqdes == -1 && errno != ENOENT) bail("mq_unlink"); mqdes = mq_open(argv[1], (O_RDWR | O_CREAT), 0600, NULL); if (mqdes == (mqd_t) -1) bail("mq_open"); memset(&sev, 0, sizeof(sev)); sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGRTMIN; sev.sigev_value = my_sigval; if (mq_notify(mqdes, &sev) == -1) bail("mq_notify"); if (mq_send(mqdes, msgbuf, sizeof(msgbuf), 0) == -1) bail("mq_send"); while (!handler_run) usleep(100000); if (mq_getattr(mqdes, &attr) == -1) bail("mq_getattr"); msglen = attr.mq_msgsize; rcvbuf = malloc(msglen); if (!rcvbuf) bail("malloc"); /* Empty the queue */ if (mq_receive(mqdes, rcvbuf, msglen, NULL) != sizeof(msgbuf)) bail("mq_receive"); /* Inhibit default SIGRTMIN handling */ sigemptyset(&mask); sigaddset(&mask, SIGRTMIN); if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) bail("sigprocmask"); /* Reregister the notifier and post another message */ if (mq_notify(mqdes, &sev) == -1) bail("mq_notify"); if (mq_send(mqdes, msgbuf, sizeof(msgbuf), 0) == -1) bail("mq_send"); sfd = signalfd(-1, &mask, 0); if (sfd == -1) bail("signalfd"); /* Handle the signal */ s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) bail("read"); assert(fdsi.ssi_code == SI_MESGQ); assert(fdsi.ssi_ptr == (unsigned long)my_sigval.sival_ptr); /* Succeeds */ assert(fdsi.ssi_int == my_sigval.sival_int); /* Fails */ exit(EXIT_SUCCESS); }