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 2023 Oxide Computer Company
14  */
15 
16 
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 
21 #include "common.h"
22 
23 int
main(void)24 main(void)
25 {
26 	int err;
27 	ssize_t sz;
28 	signalfd_siginfo_t info[3];
29 
30 	const int fd = test_basic_prep(0);
31 
32 	/* A too-small read should yield EINVAL */
33 	sz = read(fd, info, sizeof (signalfd_siginfo_t) - 1);
34 	err = errno;
35 	if (sz != -1 || errno != EINVAL) {
36 		test_fail("expected EINVAL for too-small read, "
37 		    "found res=%ld errno=%d", sz, err);
38 	}
39 
40 	const int pid = getpid();
41 
42 	/* simple single read */
43 	assert(kill(pid, SIGUSR1) == 0);
44 	sz = read(fd, info, sizeof (signalfd_siginfo_t));
45 	err = errno;
46 	if (sz != sizeof (signalfd_siginfo_t)) {
47 		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
48 	}
49 	if (info[0].ssi_signo != SIGUSR1) {
50 		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGUSR1);
51 	}
52 
53 	struct sigevent sigev = {
54 		.sigev_notify = SIGEV_SIGNAL,
55 		.sigev_signo = SIGALRM,
56 	};
57 	timer_t tid;
58 	struct itimerspec its_1ms = {
59 		.it_value = {
60 			.tv_sec = 0,
61 			.tv_nsec = MSEC2NSEC(1),
62 		}
63 	};
64 
65 	/* block for a single read: a SIGALRM 1ms in the future */
66 	assert(timer_create(CLOCK_HIGHRES, &sigev, &tid) == 0);
67 	assert(timer_settime(tid, 0, &its_1ms, NULL) == 0);
68 	sz = read(fd, info, sizeof (signalfd_siginfo_t));
69 	err = errno;
70 	if (sz != sizeof (signalfd_siginfo_t)) {
71 		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
72 	}
73 	if (info[0].ssi_signo != SIGALRM) {
74 		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGALRM);
75 	}
76 
77 	/*
78 	 * If we get a result during a read, we should not block until the
79 	 * entire buffer is full, but rather return what we have.
80 	 */
81 	assert(kill(pid, SIGUSR1) == 0);
82 	assert(kill(pid, SIGUSR2) == 0);
83 	sz = read(fd, info, sizeof (info));
84 	err = errno;
85 	if (sz != (2 * sizeof (signalfd_siginfo_t))) {
86 		test_fail("bad read result, found sz=%ld errno=%d", sz, err);
87 	}
88 	if (info[0].ssi_signo != SIGUSR1) {
89 		test_fail("bad ssi_signo %d != %d", info[0].ssi_signo, SIGUSR1);
90 	}
91 	if (info[1].ssi_signo != SIGUSR2) {
92 		test_fail("bad ssi_signo %d != %d", info[1].ssi_signo, SIGUSR2);
93 	}
94 
95 	test_pass();
96 }
97