1314817Sngie/* $NetBSD: t_sigqueue.c,v 1.7 2017/01/13 20:44:10 christos Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Christos Zoulas. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie 32272343Sngie#include <sys/cdefs.h> 33314817Sngie__RCSID("$NetBSD: t_sigqueue.c,v 1.7 2017/01/13 20:44:10 christos Exp $"); 34272343Sngie 35272343Sngie#include <atf-c.h> 36314817Sngie#include <err.h> 37272343Sngie#include <errno.h> 38272343Sngie#include <signal.h> 39314817Sngie#include <stdio.h> 40272343Sngie#include <stdlib.h> 41272343Sngie#include <sched.h> 42272343Sngie#include <unistd.h> 43272343Sngie 44272343Sngiestatic void handler(int, siginfo_t *, void *); 45272343Sngie 46272343Sngie#define VALUE (int)0xc001dad1 47272343Sngiestatic int value; 48272343Sngie 49272343Sngiestatic void 50314817Sngiehandler(int signo __unused, siginfo_t *info, void *data __unused) 51272343Sngie{ 52272343Sngie value = info->si_value.sival_int; 53272343Sngie kill(0, SIGINFO); 54272343Sngie} 55272343Sngie 56272343SngieATF_TC(sigqueue_basic); 57272343SngieATF_TC_HEAD(sigqueue_basic, tc) 58272343Sngie{ 59272343Sngie atf_tc_set_md_var(tc, "descr", "Checks sigqueue(3) sigval delivery"); 60272343Sngie} 61272343Sngie 62272343SngieATF_TC_BODY(sigqueue_basic, tc) 63272343Sngie{ 64272343Sngie struct sigaction sa; 65272343Sngie union sigval sv; 66272343Sngie 67272343Sngie sa.sa_sigaction = handler; 68272343Sngie sigemptyset(&sa.sa_mask); 69272343Sngie sa.sa_flags = SA_SIGINFO; 70272343Sngie 71272343Sngie if (sigaction(SIGUSR1, &sa, NULL) != 0) 72272343Sngie atf_tc_fail("sigaction failed"); 73272343Sngie 74272343Sngie sv.sival_int = VALUE; 75272343Sngie 76276478Sngie#ifdef __FreeBSD__ 77313498Sngie /* 78276478Sngie * From kern_sig.c: 79276478Sngie * Specification says sigqueue can only send signal to single process. 80276478Sngie */ 81276478Sngie if (sigqueue(getpid(), SIGUSR1, sv) != 0) 82276478Sngie#else 83272343Sngie if (sigqueue(0, SIGUSR1, sv) != 0) 84276478Sngie#endif 85272343Sngie atf_tc_fail("sigqueue failed"); 86272343Sngie 87272343Sngie sched_yield(); 88272343Sngie ATF_REQUIRE_EQ(sv.sival_int, value); 89272343Sngie} 90272343Sngie 91272343SngieATF_TC(sigqueue_err); 92272343SngieATF_TC_HEAD(sigqueue_err, tc) 93272343Sngie{ 94272343Sngie atf_tc_set_md_var(tc, "descr", "Test errors from sigqueue(3)"); 95272343Sngie} 96272343Sngie 97272343SngieATF_TC_BODY(sigqueue_err, tc) 98272343Sngie{ 99313498Sngie static union sigval sv; 100272343Sngie 101272343Sngie errno = 0; 102272343Sngie ATF_REQUIRE_ERRNO(EINVAL, sigqueue(getpid(), -1, sv) == -1); 103272343Sngie} 104272343Sngie 105313498Sngiestatic int signals[] = { 106313498Sngie SIGINT, SIGRTMIN + 1, SIGINT, SIGRTMIN + 0, SIGRTMIN + 2, 107313498Sngie SIGQUIT, SIGRTMIN + 1 108313498Sngie}; 109313498Sngie#ifdef __arraycount 110313498Sngie#define CNT __arraycount(signals) 111313498Sngie#else 112313498Sngie#define CNT (sizeof(signals) / sizeof(signals[0])) 113313498Sngie#endif 114313498Sngie 115313498Sngiestatic sig_atomic_t count = 0; 116313498Sngiestatic int delivered[CNT]; 117313498Sngie 118313498Sngiestatic void 119314817Sngiemyhandler(int signo, siginfo_t *info, void *context __unused) 120313498Sngie{ 121313498Sngie delivered[count++] = signo; 122313498Sngie printf("Signal #%zu: signo: %d\n", (size_t)count, signo); 123313498Sngie} 124313498Sngie 125313498Sngiestatic int 126313498Sngieasc(const void *a, const void *b) 127313498Sngie{ 128313498Sngie const int *ia = a, *ib = b; 129313498Sngie return *ib - *ia; 130313498Sngie} 131313498Sngie 132313498Sngie/* 133313498Sngie * given a array of signals to be delivered in tosend of size len 134313498Sngie * place in ordered the signals to be delivered in delivery order 135313498Sngie * and return the number of signals that should be delivered 136313498Sngie */ 137313498Sngiestatic size_t 138313498Sngiesigorder(int *ordered, const int *tosend, size_t len) 139313498Sngie{ 140313498Sngie memcpy(ordered, tosend, len * sizeof(*tosend)); 141313498Sngie qsort(ordered, len, sizeof(*ordered), asc); 142313498Sngie if (len == 1) 143313498Sngie return len; 144313498Sngie 145313498Sngie#ifdef __FreeBSD__ 146313498Sngie /* 147313498Sngie * Don't dedupe signal numbers (bug 212173) 148313498Sngie * 149313498Sngie * Per kib's comment.. 150313498Sngie * 151313498Sngie * " 152313498Sngie * OTOH, FreeBSD behaviour is to treat all signals as realtime while 153313498Sngie * there is no mem shortage and siginfo can be allocated. In 154313498Sngie * particular, signals < SIGRTMIN are not collapsed when queued more 155313498Sngie * than once. 156313498Sngie * " 157313498Sngie */ 158313498Sngie 159313498Sngie return len; 160313498Sngie#else 161313498Sngie 162313498Sngie size_t i, j; 163313498Sngie for (i = 0, j = 0; i < len - 1; i++) { 164313498Sngie if (ordered[i] >= SIGRTMIN) 165313498Sngie continue; 166313498Sngie if (j == 0) 167313498Sngie j = i + 1; 168313498Sngie while (ordered[i] == ordered[j] && j < len) 169313498Sngie j++; 170313498Sngie if (j == len) 171313498Sngie break; 172313498Sngie ordered[i + 1] = ordered[j]; 173313498Sngie } 174313498Sngie return i + 1; 175313498Sngie#endif 176313498Sngie} 177313498Sngie 178313498SngieATF_TC(sigqueue_rt); 179313498SngieATF_TC_HEAD(sigqueue_rt, tc) 180313498Sngie{ 181313498Sngie atf_tc_set_md_var(tc, "descr", "Test queuing of real-time signals"); 182313498Sngie} 183313498Sngie 184313498SngieATF_TC_BODY(sigqueue_rt, tc) 185313498Sngie{ 186313498Sngie pid_t pid; 187313498Sngie union sigval val; 188313498Sngie struct sigaction act; 189313498Sngie int ordered[CNT]; 190313498Sngie struct sigaction oact[CNT]; 191313498Sngie size_t ndelivered; 192313498Sngie 193313498Sngie ndelivered = sigorder(ordered, signals, CNT); 194313498Sngie 195313498Sngie act.sa_flags = SA_SIGINFO; 196313498Sngie act.sa_sigaction = myhandler; 197313498Sngie sigemptyset(&act.sa_mask); 198313498Sngie for (size_t i = 0; i < ndelivered; i++) 199313498Sngie ATF_REQUIRE(sigaction(ordered[i], &act, &oact[i]) != -1); 200313498Sngie 201313498Sngie val.sival_int = 0; 202313498Sngie pid = getpid(); 203313498Sngie 204313498Sngie sigset_t mask, orig; 205313498Sngie sigemptyset(&mask); 206313498Sngie for (size_t i = 0; i < CNT; i++) 207313498Sngie if (sigaddset(&mask, signals[i]) == -1) 208313498Sngie warn("sigaddset"); 209313498Sngie 210313498Sngie ATF_REQUIRE(sigprocmask(SIG_BLOCK, &mask, &orig) != -1); 211313498Sngie 212313498Sngie for (size_t i = 0; i < CNT; i++) 213313498Sngie ATF_REQUIRE(sigqueue(pid, signals[i], val) != -1); 214313498Sngie 215313498Sngie ATF_REQUIRE(sigprocmask(SIG_UNBLOCK, &mask, &orig) != -1); 216313498Sngie sleep(1); 217313498Sngie ATF_CHECK_MSG((size_t)count == ndelivered, 218313498Sngie "count %zu != ndelivered %zu", (size_t)count, ndelivered); 219313498Sngie for (size_t i = 0; i < ndelivered; i++) 220313498Sngie ATF_REQUIRE_MSG(ordered[i] == delivered[i], 221313498Sngie "%zu: ordered %d != delivered %d", 222313498Sngie i, ordered[i], delivered[i]); 223313498Sngie 224314817Sngie if ((size_t)count > ndelivered) 225314817Sngie for (size_t i = ndelivered; i < (size_t)count; i++) 226313498Sngie printf("Undelivered signal #%zu: %d\n", i, ordered[i]); 227313498Sngie 228313498Sngie for (size_t i = 0; i < ndelivered; i++) 229313498Sngie ATF_REQUIRE(sigaction(signals[i], &oact[i], NULL) != -1); 230313498Sngie} 231313498Sngie 232272343SngieATF_TP_ADD_TCS(tp) 233272343Sngie{ 234272343Sngie 235272343Sngie ATF_TP_ADD_TC(tp, sigqueue_basic); 236272343Sngie ATF_TP_ADD_TC(tp, sigqueue_err); 237313498Sngie ATF_TP_ADD_TC(tp, sigqueue_rt); 238272343Sngie 239272343Sngie return atf_no_error(); 240272343Sngie} 241