1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2013 David Hoeppner.  All rights reserved.
  14  */
  15 
  16 /*
  17  * Queue maximum number of signals and test if we can queue more signals then
  18  * allowed.
  19  */
  20 
  21 #include <sys/types.h>
  22 #include <stdarg.h>
  23 #include <stdio.h>
  24 #include <stdlib.h>
  25 #include <unistd.h>
  26 #include <signal.h>
  27 
  28 #define SIGQUEUE_SIGNAL         SIGRTMIN        /* Signal used for testing */
  29 
  30 int nreceived = 0;
  31 
  32 static void
  33 test_start(const char *test_name, const char *format, ...)
  34 {
  35         va_list args;
  36 
  37         (void) printf("TEST STARTING %s: ", test_name);
  38 
  39         va_start(args, format);
  40         (void) vprintf(format, args);
  41         va_end(args);
  42         (void) fflush(stdout);
  43 }
  44 
  45 static void
  46 test_failed(const char *test_name, const char *format, ...)
  47 {
  48         va_list args;
  49 
  50         (void) printf("TEST FAILED %s: ", test_name);
  51 
  52         va_start(args, format);
  53         (void) vprintf(format, args);
  54         va_end(args);
  55 
  56         (void) exit(-1);
  57 }
  58 
  59 static void
  60 test_passed(const char *test_name)
  61 {
  62         (void) printf("TEST PASS: %s\n", test_name);
  63         (void) fflush(stdout);
  64 }
  65 
  66 /* ARGSUSED */
  67 static void
  68 maximum_test_handler(int signal, siginfo_t *siginfo, void *context)
  69 {
  70         nreceived++;
  71 }
  72 
  73 static void
  74 sigqueue_maximum_test(void)
  75 {
  76         const char *test_name = __func__;
  77         struct sigaction action;
  78         long sigqueue_max, i;
  79         pid_t pid;
  80         union sigval value;
  81         int error;
  82 
  83         test_start(test_name, "queue maximum number of signals\n");
  84 
  85         /*
  86          * Get the maximum size of the queue.
  87          */
  88         sigqueue_max = sysconf(_SC_SIGQUEUE_MAX);
  89         if (sigqueue_max == -1) {
  90                 test_failed(test_name, "sysconf\n");
  91         }
  92 
  93         /*
  94          * Put the signal on hold.
  95          */
  96         error = sighold(SIGQUEUE_SIGNAL);
  97         if (error == -1) {
  98                 test_failed(test_name, "sighold\n");
  99         }
 100 
 101         pid = getpid();
 102         value.sival_int = 0;
 103 
 104         action.sa_flags = SA_SIGINFO;
 105         action.sa_sigaction = maximum_test_handler;
 106 
 107         error = sigemptyset(&action.sa_mask);
 108         if (error == -1) {
 109                 test_failed(test_name, "sigemptyset\n");
 110         }
 111 
 112         /*
 113          * Set signal handler.
 114          */
 115         error = sigaction(SIGQUEUE_SIGNAL, &action, 0);
 116         if (error == -1) {
 117                 test_failed(test_name, "sigaction\n");
 118         }
 119 
 120         /*
 121          * Fill the signal queue to the maximum.
 122          */
 123         for (i = 0; i < sigqueue_max; i++) {
 124                 error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
 125                 if (error == -1) {
 126                         test_failed(test_name, "sigqueue\n");
 127                 }
 128         }
 129 
 130         /*
 131          * Send a further signal and test if we get the expected
 132          * error.
 133          */
 134         error = sigqueue(pid, SIGQUEUE_SIGNAL, value);
 135         if (error != -1) {
 136                 test_failed(test_name, "sigqueue\n");
 137         }
 138 
 139         /*
 140          * Unblock the signals and check if we received all messages
 141          * from the signal queue.
 142          */
 143         error = sigrelse(SIGQUEUE_SIGNAL);
 144         if (error == -1) {
 145                 test_failed(test_name, "sigrelse\n");
 146         }
 147 
 148         if (nreceived != sigqueue_max) {
 149                 test_failed(test_name, "nreveived != sigqueue_max\n");
 150         }
 151 
 152         test_passed(test_name);
 153 }
 154 
 155 static void
 156 run_tests(void)
 157 {
 158         sigqueue_maximum_test();
 159 }
 160 
 161 /* ARGSUSED */
 162 int
 163 main(int argc, char *argv[])
 164 {
 165         run_tests();
 166 
 167         return (EXIT_SUCCESS);
 168 }