1d7b0e9cngie/* $NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 christos Exp $ */
25eef524ngie
35eef524ngie/*-
45eef524ngie * Copyright (c) 2011 The NetBSD Foundation, Inc.
55eef524ngie * All rights reserved.
65eef524ngie *
75eef524ngie * This code is derived from software contributed to The NetBSD Foundation
85eef524ngie * by Jukka Ruohonen.
95eef524ngie *
105eef524ngie * Redistribution and use in source and binary forms, with or without
115eef524ngie * modification, are permitted provided that the following conditions
125eef524ngie * are met:
135eef524ngie * 1. Redistributions of source code must retain the above copyright
145eef524ngie *    notice, this list of conditions and the following disclaimer.
155eef524ngie * 2. Redistributions in binary form must reproduce the above copyright
165eef524ngie *    notice, this list of conditions and the following disclaimer in the
175eef524ngie *    documentation and/or other materials provided with the distribution.
185eef524ngie *
195eef524ngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
205eef524ngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
215eef524ngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
225eef524ngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
235eef524ngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
245eef524ngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
255eef524ngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
265eef524ngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275eef524ngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
285eef524ngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
295eef524ngie * POSSIBILITY OF SUCH DAMAGE.
305eef524ngie */
315eef524ngie#include <sys/cdefs.h>
32d7b0e9cngie__RCSID("$NetBSD: t_nanosleep.c,v 1.4 2017/01/13 21:15:14 christos Exp $");
335eef524ngie
345eef524ngie#include <sys/time.h>
355eef524ngie#include <sys/wait.h>
365eef524ngie
375eef524ngie#include <atf-c.h>
385eef524ngie#include <errno.h>
395eef524ngie#include <time.h>
405eef524ngie#include <signal.h>
415eef524ngie#include <stdio.h>
425eef524ngie#include <stdlib.h>
435eef524ngie#include <string.h>
445eef524ngie#include <sysexits.h>
455eef524ngie#include <unistd.h>
465eef524ngie
475eef524ngiestatic void
48d7b0e9cngiehandler(int signo __unused)
495eef524ngie{
505eef524ngie	/* Nothing. */
515eef524ngie}
525eef524ngie
53db51b6bbdrewerystatic int got_info;
54db51b6bbdrewerystatic void
55db51b6bbdreweryinfo_handler(int signo __unused)
56db51b6bbdrewery{
57db51b6bbdrewery
58db51b6bbdrewery	got_info = 1;
59db51b6bbdrewery}
60db51b6bbdrewery
61db51b6bbdrewery
625eef524ngieATF_TC(nanosleep_basic);
635eef524ngieATF_TC_HEAD(nanosleep_basic, tc)
645eef524ngie{
655eef524ngie	atf_tc_set_md_var(tc, "descr", "Test that nanosleep(2) works");
665eef524ngie}
675eef524ngie
685eef524ngieATF_TC_BODY(nanosleep_basic, tc)
695eef524ngie{
705eef524ngie	static const size_t maxiter = 10;
715eef524ngie	struct timespec ts1, ts2, tsn;
725eef524ngie	size_t i;
735eef524ngie
745eef524ngie	for (i = 1; i < maxiter; i++) {
755eef524ngie
765eef524ngie		tsn.tv_sec = 0;
775eef524ngie		tsn.tv_nsec = i;
785eef524ngie
795eef524ngie		(void)memset(&ts1, 0, sizeof(struct timespec));
805eef524ngie		(void)memset(&ts2, 0, sizeof(struct timespec));
815eef524ngie
825eef524ngie		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
835eef524ngie		ATF_REQUIRE(nanosleep(&tsn, NULL) == 0);
845eef524ngie		ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
855eef524ngie
865eef524ngie		/*
875eef524ngie		 * Verify that we slept at least one nanosecond.
885eef524ngie		 */
895eef524ngie		if (timespeccmp(&ts2, &ts1, <=) != 0) {
905eef524ngie
915eef524ngie			(void)fprintf(stderr,
925eef524ngie			    "sleep time:: sec %llu, nsec %lu\n\t\t"
935eef524ngie			    "ts1: sec %llu, nsec %lu\n\t\t"
945eef524ngie			    "ts2: sec %llu, nsec %lu\n",
955eef524ngie			    (unsigned long long)tsn.tv_sec, tsn.tv_nsec,
965eef524ngie			    (unsigned long long)ts1.tv_sec, ts1.tv_nsec,
975eef524ngie			    (unsigned long long)ts2.tv_sec, ts2.tv_nsec);
985eef524ngie
995eef524ngie			atf_tc_fail_nonfatal("inaccuracies in sleep time "
1005eef524ngie			    "(resolution = %lu nsec)", tsn.tv_nsec);
1015eef524ngie		}
1025eef524ngie	}
1035eef524ngie}
1045eef524ngie
1055eef524ngieATF_TC(nanosleep_err);
1065eef524ngieATF_TC_HEAD(nanosleep_err, tc)
1075eef524ngie{
1085eef524ngie	atf_tc_set_md_var(tc, "descr",
1095eef524ngie	    "Test errors from nanosleep(2) (PR bin/14558)");
1105eef524ngie}
1115eef524ngie
1125eef524ngieATF_TC_BODY(nanosleep_err, tc)
1135eef524ngie{
1145eef524ngie	struct timespec ts;
1155eef524ngie
1165eef524ngie	ts.tv_sec = 1;
1175eef524ngie	ts.tv_nsec = -1;
1185eef524ngie	errno = 0;
1195eef524ngie	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
1205eef524ngie
1215eef524ngie	ts.tv_sec = 1;
1225eef524ngie	ts.tv_nsec = 1000000000;
1235eef524ngie	errno = 0;
1245eef524ngie	ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
1255eef524ngie
1265eef524ngie	ts.tv_sec = -1;
1275eef524ngie	ts.tv_nsec = 0;
1285eef524ngie	errno = 0;
1295eef524ngie	ATF_REQUIRE_ERRNO(0, nanosleep(&ts, NULL) == 0);
1305eef524ngie
1315eef524ngie	errno = 0;
1325eef524ngie	ATF_REQUIRE_ERRNO(EFAULT, nanosleep((void *)-1, NULL) == -1);
1335eef524ngie}
1345eef524ngie
1355eef524ngieATF_TC(nanosleep_sig);
1365eef524ngieATF_TC_HEAD(nanosleep_sig, tc)
1375eef524ngie{
1385eef524ngie	atf_tc_set_md_var(tc, "descr", "Test signal for nanosleep(2)");
1395eef524ngie}
1405eef524ngie
1415eef524ngieATF_TC_BODY(nanosleep_sig, tc)
1425eef524ngie{
1435eef524ngie	struct timespec tsn, tsr;
1445eef524ngie	pid_t pid;
1455eef524ngie	int sta;
1465eef524ngie
1475eef524ngie	/*
1485eef524ngie	 * Test that a signal interrupts nanosleep(2).
1495eef524ngie	 *
1505eef524ngie	 * (In which case the return value should be -1 and the
1515eef524ngie	 * second parameter should contain the unslept time.)
1525eef524ngie	 */
1535eef524ngie	pid = fork();
1545eef524ngie
1555eef524ngie	ATF_REQUIRE(pid >= 0);
1565eef524ngie	ATF_REQUIRE(signal(SIGINT, handler) == 0);
1575eef524ngie
1585eef524ngie	if (pid == 0) {
1595eef524ngie
1605eef524ngie		tsn.tv_sec = 10;
1615eef524ngie		tsn.tv_nsec = 0;
1625eef524ngie
1635eef524ngie		tsr.tv_sec = 0;
1645eef524ngie		tsr.tv_nsec = 0;
1655eef524ngie
1665eef524ngie		errno = 0;
1675eef524ngie
1685eef524ngie		if (nanosleep(&tsn, &tsr) != -1)
1695eef524ngie			_exit(EXIT_FAILURE);
1705eef524ngie
1715eef524ngie		if (errno != EINTR)
1725eef524ngie			_exit(EXIT_FAILURE);
1735eef524ngie
1745eef524ngie		if (tsr.tv_sec == 0 && tsr.tv_nsec == 0)
1755eef524ngie			_exit(EXIT_FAILURE);
1765eef524ngie
1775eef524ngie		_exit(EXIT_SUCCESS);
1785eef524ngie	}
1795eef524ngie
1805eef524ngie	(void)sleep(1);
1815eef524ngie	(void)kill(pid, SIGINT);
1825eef524ngie	(void)wait(&sta);
1835eef524ngie
1845eef524ngie	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
1855eef524ngie		atf_tc_fail("signal did not interrupt nanosleep(2)");
1865eef524ngie}
1875eef524ngie
188db51b6bbdreweryATF_TC(nanosleep_eintr);
189db51b6bbdreweryATF_TC_HEAD(nanosleep_eintr, tc)
190db51b6bbdrewery{
191db51b6bbdrewery	atf_tc_set_md_var(tc, "descr", "Test [EINTR] for nanosleep(2)");
192db51b6bbdrewery	atf_tc_set_md_var(tc, "timeout", "7");
193db51b6bbdrewery}
194db51b6bbdrewery
195db51b6bbdreweryATF_TC_BODY(nanosleep_eintr, tc)
196db51b6bbdrewery{
197db51b6bbdrewery	struct sigaction act;
198db51b6bbdrewery	struct timespec tso, ts;
199db51b6bbdrewery	pid_t pid;
200db51b6bbdrewery	int sta;
201db51b6bbdrewery
202db51b6bbdrewery	/*
203db51b6bbdrewery	 * Test that [EINTR] properly handles rmtp for nanosleep(2).
204db51b6bbdrewery	 */
205db51b6bbdrewery	pid = fork();
206db51b6bbdrewery
207db51b6bbdrewery	ATF_REQUIRE(pid >= 0);
208db51b6bbdrewery
209db51b6bbdrewery	got_info = 0;
210db51b6bbdrewery
211db51b6bbdrewery	if (pid == 0) {
212db51b6bbdrewery		act.sa_handler = info_handler;
213db51b6bbdrewery		sigemptyset(&act.sa_mask);
214db51b6bbdrewery		act.sa_flags = 0; /* Don't allow restart. */
215db51b6bbdrewery		ATF_REQUIRE(sigaction(SIGINFO, &act, NULL) == 0);
216db51b6bbdrewery
217db51b6bbdrewery		tso.tv_sec = 5;
218db51b6bbdrewery		tso.tv_nsec = 0;
219db51b6bbdrewery
220db51b6bbdrewery		ts.tv_sec = tso.tv_sec;
221db51b6bbdrewery		ts.tv_nsec = tso.tv_nsec;
222db51b6bbdrewery
223db51b6bbdrewery		errno = 0;
224db51b6bbdrewery		while (nanosleep(&ts, &ts) != 0) {
225db51b6bbdrewery			ATF_REQUIRE_MSG(timespeccmp(&ts, &tso, <=),
226db51b6bbdrewery			    "errno=%d ts=%0.9f should be <= last tso=%0.9f\n",
227db51b6bbdrewery			    errno,
228db51b6bbdrewery			    ts.tv_sec + ts.tv_nsec / 1e9,
229db51b6bbdrewery			    tso.tv_sec + tso.tv_nsec / 1e9);
230db51b6bbdrewery			if (errno == EINTR && got_info == 1) {
231db51b6bbdrewery				got_info = 0;
232db51b6bbdrewery				errno = 0;
233db51b6bbdrewery				tso.tv_sec = ts.tv_sec;
234db51b6bbdrewery				tso.tv_nsec = ts.tv_nsec;
235db51b6bbdrewery				continue;
236db51b6bbdrewery			}
237db51b6bbdrewery			_exit(EXIT_FAILURE);
238db51b6bbdrewery		}
239db51b6bbdrewery
240db51b6bbdrewery		if (errno != 0)
241db51b6bbdrewery			_exit(EXIT_FAILURE);
242db51b6bbdrewery
243db51b6bbdrewery		_exit(EXIT_SUCCESS);
244db51b6bbdrewery	}
245db51b6bbdrewery
246db51b6bbdrewery	/* Flood the process with SIGINFO until it exits. */
247db51b6bbdrewery	do {
248db51b6bbdrewery		for (int i = 0; i < 10; i++)
249db51b6bbdrewery			ATF_REQUIRE(kill(pid, SIGINFO) == 0);
250db51b6bbdrewery		ATF_REQUIRE(usleep(10000) == 0);
251db51b6bbdrewery	} while (waitpid(pid, &sta, WNOHANG) == 0);
252db51b6bbdrewery
253db51b6bbdrewery	ATF_REQUIRE(WIFEXITED(sta) == 1);
254db51b6bbdrewery
255db51b6bbdrewery	if (WEXITSTATUS(sta) != EXIT_SUCCESS)
256db51b6bbdrewery		atf_tc_fail("nanosleep(2) handled rtmp incorrectly");
257db51b6bbdrewery}
258db51b6bbdrewery
2595eef524ngieATF_TP_ADD_TCS(tp)
2605eef524ngie{
2615eef524ngie
2625eef524ngie	ATF_TP_ADD_TC(tp, nanosleep_basic);
2635eef524ngie	ATF_TP_ADD_TC(tp, nanosleep_err);
2645eef524ngie	ATF_TP_ADD_TC(tp, nanosleep_sig);
265db51b6bbdrewery	ATF_TP_ADD_TC(tp, nanosleep_eintr);
2665eef524ngie
2675eef524ngie	return atf_no_error();
2685eef524ngie}
269