1314817Sngie/* $NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 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 Jukka Ruohonen.
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#include <sys/cdefs.h>
32314817Sngie__RCSID("$NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 christos Exp $");
33272343Sngie
34272343Sngie#include <sys/time.h>
35272343Sngie#include <sys/wait.h>
36272343Sngie
37272343Sngie#include <atf-c.h>
38272343Sngie#include <errno.h>
39272343Sngie#include <time.h>
40272343Sngie#include <signal.h>
41272343Sngie#include <stdio.h>
42272343Sngie#include <stdlib.h>
43272343Sngie#include <string.h>
44272343Sngie#include <sysexits.h>
45272343Sngie#include <unistd.h>
46272343Sngie
47272343Sngiestatic void
48276478Sngiehandler(int signo __unused)
49272343Sngie{
50272343Sngie	/* Nothing. */
51272343Sngie}
52272343Sngie
53330422Sbdrewerystatic int got_info;
54330422Sbdrewerystatic void
55330422Sbdreweryinfo_handler(int signo __unused)
56330422Sbdrewery{
57330422Sbdrewery
58330422Sbdrewery	got_info = 1;
59330422Sbdrewery}
60330422Sbdrewery
61330422Sbdrewery
62272343SngieATF_TC(nanosleep_basic);
63272343SngieATF_TC_HEAD(nanosleep_basic, tc)
64272343Sngie{
65272343Sngie	atf_tc_set_md_var(tc, "descr", "Test that nanosleep(2) works");
66272343Sngie}
67272343Sngie
68272343SngieATF_TC_BODY(nanosleep_basic, tc)
69272343Sngie{
70272343Sngie	static const size_t maxiter = 10;
71272343Sngie	struct timespec ts1, ts2, tsn;
72272343Sngie	size_t i;
73272343Sngie
74272343Sngie	for (i = 1; i < maxiter; i++) {
75272343Sngie
76272343Sngie		tsn.tv_sec = 0;
77272343Sngie		tsn.tv_nsec = i;
78272343Sngie
79272343Sngie		(void)memset(&ts1, 0, sizeof(struct timespec));
80272343Sngie		(void)memset(&ts2, 0, sizeof(struct timespec));
81272343Sngie
82272343Sngie		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
83272343Sngie		ATF_REQUIRE(nanosleep(&tsn, NULL) == 0);
84272343Sngie		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
85272343Sngie
86272343Sngie		/*
87272343Sngie		 * Verify that we slept at least one nanosecond.
88272343Sngie		 */
89272343Sngie		if (timespeccmp(&ts2, &ts1, <=) != 0) {
90272343Sngie
91272343Sngie			(void)fprintf(stderr,
92272343Sngie			    "sleep time:: sec %llu, nsec %lu\n\t\t"
93272343Sngie			    "ts1: sec %llu, nsec %lu\n\t\t"
94272343Sngie			    "ts2: sec %llu, nsec %lu\n",
95272343Sngie			    (unsigned long long)tsn.tv_sec, tsn.tv_nsec,
96272343Sngie			    (unsigned long long)ts1.tv_sec, ts1.tv_nsec,
97272343Sngie			    (unsigned long long)ts2.tv_sec, ts2.tv_nsec);
98272343Sngie
99272343Sngie			atf_tc_fail_nonfatal("inaccuracies in sleep time "
100272343Sngie			    "(resolution = %lu nsec)", tsn.tv_nsec);
101272343Sngie		}
102272343Sngie	}
103272343Sngie}
104272343Sngie
105272343SngieATF_TC(nanosleep_err);
106272343SngieATF_TC_HEAD(nanosleep_err, tc)
107272343Sngie{
108272343Sngie	atf_tc_set_md_var(tc, "descr",
109272343Sngie	    "Test errors from nanosleep(2) (PR bin/14558)");
110272343Sngie}
111272343Sngie
112272343SngieATF_TC_BODY(nanosleep_err, tc)
113272343Sngie{
114272343Sngie	struct timespec ts;
115272343Sngie
116272343Sngie	ts.tv_sec = 1;
117272343Sngie	ts.tv_nsec = -1;
118272343Sngie	errno = 0;
119272343Sngie	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
120272343Sngie
121272343Sngie	ts.tv_sec = 1;
122272343Sngie	ts.tv_nsec = 1000000000;
123272343Sngie	errno = 0;
124272343Sngie	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
125272343Sngie
126272343Sngie	ts.tv_sec = -1;
127272343Sngie	ts.tv_nsec = 0;
128272343Sngie	errno = 0;
129272343Sngie	ATF_REQUIRE_ERRNO(0, nanosleep(&ts, NULL) == 0);
130272343Sngie
131272343Sngie	errno = 0;
132272343Sngie	ATF_REQUIRE_ERRNO(EFAULT, nanosleep((void *)-1, NULL) == -1);
133272343Sngie}
134272343Sngie
135272343SngieATF_TC(nanosleep_sig);
136272343SngieATF_TC_HEAD(nanosleep_sig, tc)
137272343Sngie{
138272343Sngie	atf_tc_set_md_var(tc, "descr", "Test signal for nanosleep(2)");
139272343Sngie}
140272343Sngie
141272343SngieATF_TC_BODY(nanosleep_sig, tc)
142272343Sngie{
143272343Sngie	struct timespec tsn, tsr;
144272343Sngie	pid_t pid;
145272343Sngie	int sta;
146272343Sngie
147272343Sngie	/*
148272343Sngie	 * Test that a signal interrupts nanosleep(2).
149272343Sngie	 *
150272343Sngie	 * (In which case the return value should be -1 and the
151272343Sngie	 * second parameter should contain the unslept time.)
152272343Sngie	 */
153272343Sngie	pid = fork();
154272343Sngie
155272343Sngie	ATF_REQUIRE(pid >= 0);
156272343Sngie	ATF_REQUIRE(signal(SIGINT, handler) == 0);
157272343Sngie
158272343Sngie	if (pid == 0) {
159272343Sngie
160272343Sngie		tsn.tv_sec = 10;
161272343Sngie		tsn.tv_nsec = 0;
162272343Sngie
163272343Sngie		tsr.tv_sec = 0;
164272343Sngie		tsr.tv_nsec = 0;
165272343Sngie
166272343Sngie		errno = 0;
167272343Sngie
168272343Sngie		if (nanosleep(&tsn, &tsr) != -1)
169272343Sngie			_exit(EXIT_FAILURE);
170272343Sngie
171272343Sngie		if (errno != EINTR)
172272343Sngie			_exit(EXIT_FAILURE);
173272343Sngie
174272343Sngie		if (tsr.tv_sec == 0 && tsr.tv_nsec == 0)
175272343Sngie			_exit(EXIT_FAILURE);
176272343Sngie
177272343Sngie		_exit(EXIT_SUCCESS);
178272343Sngie	}
179272343Sngie
180272343Sngie	(void)sleep(1);
181272343Sngie	(void)kill(pid, SIGINT);
182272343Sngie	(void)wait(&sta);
183272343Sngie
184272343Sngie	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
185272343Sngie		atf_tc_fail("signal did not interrupt nanosleep(2)");
186272343Sngie}
187272343Sngie
188330422SbdreweryATF_TC(nanosleep_eintr);
189330422SbdreweryATF_TC_HEAD(nanosleep_eintr, tc)
190330422Sbdrewery{
191330422Sbdrewery	atf_tc_set_md_var(tc, "descr", "Test [EINTR] for nanosleep(2)");
192330422Sbdrewery	atf_tc_set_md_var(tc, "timeout", "7");
193330422Sbdrewery}
194330422Sbdrewery
195330422SbdreweryATF_TC_BODY(nanosleep_eintr, tc)
196330422Sbdrewery{
197330422Sbdrewery	struct sigaction act;
198330422Sbdrewery	struct timespec tso, ts;
199330422Sbdrewery	pid_t pid;
200330422Sbdrewery	int sta;
201330422Sbdrewery
202330422Sbdrewery	/*
203330422Sbdrewery	 * Test that [EINTR] properly handles rmtp for nanosleep(2).
204330422Sbdrewery	 */
205330422Sbdrewery	pid = fork();
206330422Sbdrewery
207330422Sbdrewery	ATF_REQUIRE(pid >= 0);
208330422Sbdrewery
209330422Sbdrewery	got_info = 0;
210330422Sbdrewery
211330422Sbdrewery	if (pid == 0) {
212330422Sbdrewery		act.sa_handler = info_handler;
213330422Sbdrewery		sigemptyset(&act.sa_mask);
214330422Sbdrewery		act.sa_flags = 0; /* Don't allow restart. */
215330422Sbdrewery		ATF_REQUIRE(sigaction(SIGINFO, &act, NULL) == 0);
216330422Sbdrewery
217330422Sbdrewery		tso.tv_sec = 5;
218330422Sbdrewery		tso.tv_nsec = 0;
219330422Sbdrewery
220330422Sbdrewery		ts.tv_sec = tso.tv_sec;
221330422Sbdrewery		ts.tv_nsec = tso.tv_nsec;
222330422Sbdrewery
223330422Sbdrewery		errno = 0;
224330422Sbdrewery		while (nanosleep(&ts, &ts) != 0) {
225330422Sbdrewery			ATF_REQUIRE_MSG(timespeccmp(&ts, &tso, <=),
226330422Sbdrewery			    "errno=%d ts=%0.9f should be <= last tso=%0.9f\n",
227330422Sbdrewery			    errno,
228330422Sbdrewery			    ts.tv_sec + ts.tv_nsec / 1e9,
229330422Sbdrewery			    tso.tv_sec + tso.tv_nsec / 1e9);
230330422Sbdrewery			if (errno == EINTR && got_info == 1) {
231330422Sbdrewery				got_info = 0;
232330422Sbdrewery				errno = 0;
233330422Sbdrewery				tso.tv_sec = ts.tv_sec;
234330422Sbdrewery				tso.tv_nsec = ts.tv_nsec;
235330422Sbdrewery				continue;
236330422Sbdrewery			}
237330422Sbdrewery			_exit(EXIT_FAILURE);
238330422Sbdrewery		}
239330422Sbdrewery
240330422Sbdrewery		if (errno != 0)
241330422Sbdrewery			_exit(EXIT_FAILURE);
242330422Sbdrewery
243330422Sbdrewery		_exit(EXIT_SUCCESS);
244330422Sbdrewery	}
245330422Sbdrewery
246330422Sbdrewery	/* Flood the process with SIGINFO until it exits. */
247330422Sbdrewery	do {
248330422Sbdrewery		for (int i = 0; i < 10; i++)
249330422Sbdrewery			ATF_REQUIRE(kill(pid, SIGINFO) == 0);
250330422Sbdrewery		ATF_REQUIRE(usleep(10000) == 0);
251330422Sbdrewery	} while (waitpid(pid, &sta, WNOHANG) == 0);
252330422Sbdrewery
253330422Sbdrewery	ATF_REQUIRE(WIFEXITED(sta) == 1);
254330422Sbdrewery
255330422Sbdrewery	if (WEXITSTATUS(sta) != EXIT_SUCCESS)
256330422Sbdrewery		atf_tc_fail("nanosleep(2) handled rtmp incorrectly");
257330422Sbdrewery}
258330422Sbdrewery
259272343SngieATF_TP_ADD_TCS(tp)
260272343Sngie{
261272343Sngie
262272343Sngie	ATF_TP_ADD_TC(tp, nanosleep_basic);
263272343Sngie	ATF_TP_ADD_TC(tp, nanosleep_err);
264272343Sngie	ATF_TP_ADD_TC(tp, nanosleep_sig);
265330422Sbdrewery	ATF_TP_ADD_TC(tp, nanosleep_eintr);
266272343Sngie
267272343Sngie	return atf_no_error();
268272343Sngie}
269