Home | History | Annotate | Line # | Download | only in sys
t_poll.c revision 1.3.34.2
      1  1.3.34.2  martin /*	$NetBSD: t_poll.c,v 1.3.34.2 2021/10/04 14:32:38 martin Exp $	*/
      2       1.1  jruoho 
      3       1.1  jruoho /*-
      4       1.1  jruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5       1.1  jruoho  * All rights reserved.
      6       1.1  jruoho  *
      7       1.1  jruoho  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1  jruoho  * by Matthias Scheler.
      9       1.1  jruoho  *
     10       1.1  jruoho  * Redistribution and use in source and binary forms, with or without
     11       1.1  jruoho  * modification, are permitted provided that the following conditions
     12       1.1  jruoho  * are met:
     13       1.1  jruoho  * 1. Redistributions of source code must retain the above copyright
     14       1.1  jruoho  *    notice, this list of conditions and the following disclaimer.
     15       1.1  jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  jruoho  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  jruoho  *    documentation and/or other materials provided with the distribution.
     18       1.1  jruoho  *
     19       1.1  jruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1  jruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1  jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1  jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1  jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1  jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1  jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1  jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1  jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1  jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1  jruoho  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1  jruoho  */
     31       1.1  jruoho 
     32  1.3.34.1  martin #include <sys/stat.h>
     33       1.1  jruoho #include <sys/time.h>
     34       1.2  jruoho #include <sys/wait.h>
     35       1.1  jruoho 
     36       1.1  jruoho #include <atf-c.h>
     37       1.1  jruoho #include <errno.h>
     38       1.1  jruoho #include <fcntl.h>
     39       1.1  jruoho #include <paths.h>
     40       1.1  jruoho #include <poll.h>
     41       1.2  jruoho #include <stdio.h>
     42  1.3.34.2  martin #include <stdlib.h>
     43       1.1  jruoho #include <signal.h>
     44       1.1  jruoho #include <unistd.h>
     45       1.1  jruoho 
     46       1.2  jruoho static int desc;
     47       1.2  jruoho 
     48       1.2  jruoho static void
     49       1.2  jruoho child1(void)
     50       1.2  jruoho {
     51       1.2  jruoho 	struct pollfd pfd;
     52       1.2  jruoho 
     53       1.2  jruoho 	pfd.fd = desc;
     54       1.2  jruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     55       1.2  jruoho 
     56       1.2  jruoho 	(void)poll(&pfd, 1, 2000);
     57       1.2  jruoho 	(void)printf("child1 exit\n");
     58       1.2  jruoho }
     59       1.2  jruoho 
     60       1.2  jruoho static void
     61       1.2  jruoho child2(void)
     62       1.2  jruoho {
     63       1.2  jruoho 	struct pollfd pfd;
     64       1.2  jruoho 
     65       1.2  jruoho 	pfd.fd = desc;
     66       1.2  jruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     67       1.2  jruoho 
     68       1.2  jruoho 	(void)sleep(1);
     69       1.2  jruoho 	(void)poll(&pfd, 1, INFTIM);
     70       1.2  jruoho 	(void)printf("child2 exit\n");
     71       1.2  jruoho }
     72       1.2  jruoho 
     73       1.2  jruoho static void
     74       1.2  jruoho child3(void)
     75       1.2  jruoho {
     76       1.2  jruoho 	struct pollfd pfd;
     77       1.2  jruoho 
     78       1.2  jruoho 	(void)sleep(5);
     79       1.2  jruoho 
     80       1.2  jruoho 	pfd.fd = desc;
     81       1.2  jruoho 	pfd.events = POLLIN | POLLHUP | POLLOUT;
     82       1.2  jruoho 
     83       1.2  jruoho 	(void)poll(&pfd, 1, INFTIM);
     84       1.2  jruoho 	(void)printf("child3 exit\n");
     85       1.2  jruoho }
     86       1.2  jruoho 
     87       1.2  jruoho ATF_TC(poll_3way);
     88       1.2  jruoho ATF_TC_HEAD(poll_3way, tc)
     89       1.2  jruoho {
     90       1.2  jruoho 	atf_tc_set_md_var(tc, "timeout", "15");
     91       1.2  jruoho 	atf_tc_set_md_var(tc, "descr",
     92       1.2  jruoho 	    "Check for 3-way collision for descriptor. First child comes "
     93       1.2  jruoho 	    "and polls on descriptor, second child comes and polls, first "
     94       1.2  jruoho 	    "child times out and exits, third child comes and polls. When "
     95       1.2  jruoho 	    "the wakeup event happens, the two remaining children should "
     96       1.2  jruoho 	    "both be awaken. (kern/17517)");
     97       1.2  jruoho }
     98       1.2  jruoho 
     99       1.2  jruoho ATF_TC_BODY(poll_3way, tc)
    100       1.2  jruoho {
    101       1.2  jruoho 	int pf[2];
    102       1.2  jruoho 	int status, i;
    103       1.2  jruoho 	pid_t pid;
    104       1.2  jruoho 
    105       1.2  jruoho 	pipe(pf);
    106       1.2  jruoho 	desc = pf[0];
    107       1.2  jruoho 
    108       1.2  jruoho 	pid = fork();
    109       1.2  jruoho 	ATF_REQUIRE(pid >= 0);
    110       1.2  jruoho 
    111       1.2  jruoho 	if (pid == 0) {
    112       1.2  jruoho 		(void)close(pf[1]);
    113       1.2  jruoho 		child1();
    114       1.2  jruoho 		_exit(0);
    115       1.2  jruoho 		/* NOTREACHED */
    116       1.2  jruoho 	}
    117       1.2  jruoho 
    118       1.2  jruoho 	pid = fork();
    119       1.2  jruoho 	ATF_REQUIRE(pid >= 0);
    120       1.2  jruoho 
    121       1.2  jruoho 	if (pid == 0) {
    122       1.2  jruoho 		(void)close(pf[1]);
    123       1.2  jruoho 		child2();
    124       1.2  jruoho 		_exit(0);
    125       1.2  jruoho 		/* NOTREACHED */
    126       1.2  jruoho 	}
    127       1.2  jruoho 
    128       1.2  jruoho 	pid = fork();
    129       1.2  jruoho 	ATF_REQUIRE( pid >= 0);
    130       1.2  jruoho 
    131       1.2  jruoho 	if (pid == 0) {
    132       1.2  jruoho 		(void)close(pf[1]);
    133       1.2  jruoho 		child3();
    134       1.2  jruoho 		_exit(0);
    135       1.2  jruoho 		/* NOTREACHED */
    136       1.2  jruoho 	}
    137       1.2  jruoho 
    138       1.2  jruoho 	(void)sleep(10);
    139       1.2  jruoho 
    140       1.2  jruoho 	(void)printf("parent write\n");
    141       1.2  jruoho 
    142       1.2  jruoho 	ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
    143       1.2  jruoho 
    144       1.2  jruoho 	for(i = 0; i < 3; ++i)
    145       1.2  jruoho 		(void)wait(&status);
    146       1.2  jruoho 
    147       1.2  jruoho 	(void)printf("parent terminated\n");
    148       1.2  jruoho }
    149       1.2  jruoho 
    150       1.1  jruoho ATF_TC(poll_basic);
    151       1.1  jruoho ATF_TC_HEAD(poll_basic, tc)
    152       1.1  jruoho {
    153       1.1  jruoho 	atf_tc_set_md_var(tc, "timeout", "10");
    154       1.1  jruoho 	atf_tc_set_md_var(tc, "descr",
    155       1.1  jruoho 	    "Basis functionality test for poll(2)");
    156       1.1  jruoho }
    157       1.1  jruoho 
    158       1.1  jruoho ATF_TC_BODY(poll_basic, tc)
    159       1.1  jruoho {
    160       1.1  jruoho 	int fds[2];
    161       1.1  jruoho 	struct pollfd pfds[2];
    162       1.1  jruoho 	int ret;
    163       1.1  jruoho 
    164       1.1  jruoho 	ATF_REQUIRE_EQ(pipe(fds), 0);
    165       1.1  jruoho 
    166       1.1  jruoho 	pfds[0].fd = fds[0];
    167       1.1  jruoho 	pfds[0].events = POLLIN;
    168       1.1  jruoho 	pfds[1].fd = fds[1];
    169       1.1  jruoho 	pfds[1].events = POLLOUT;
    170       1.1  jruoho 
    171       1.1  jruoho 	/*
    172       1.1  jruoho 	 * Check that we get a timeout waiting for data on the read end
    173       1.1  jruoho 	 * of our pipe.
    174       1.1  jruoho 	 */
    175       1.1  jruoho 	pfds[0].revents = -1;
    176       1.1  jruoho 	pfds[1].revents = -1;
    177       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
    178       1.1  jruoho 	    "got: %d", ret);
    179       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    180       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
    181       1.1  jruoho 
    182       1.1  jruoho 	/* Check that the write end of the pipe as reported as ready. */
    183       1.1  jruoho 	pfds[0].revents = -1;
    184       1.1  jruoho 	pfds[1].revents = -1;
    185       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
    186       1.1  jruoho 	    "got: %d", ret);
    187       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
    188       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
    189       1.1  jruoho 	    pfds[1].revents);
    190       1.1  jruoho 
    191       1.1  jruoho 	/* Check that only the write end of the pipe as reported as ready. */
    192       1.1  jruoho 	pfds[0].revents = -1;
    193       1.1  jruoho 	pfds[1].revents = -1;
    194       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
    195       1.1  jruoho 	    "got: %d", ret);
    196       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    197       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    198       1.1  jruoho 	    pfds[1].revents);
    199       1.1  jruoho 
    200       1.1  jruoho 	/* Write data to our pipe. */
    201       1.1  jruoho 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
    202       1.1  jruoho 
    203       1.1  jruoho 	/* Check that both ends of our pipe are reported as ready. */
    204       1.1  jruoho 	pfds[0].revents = -1;
    205       1.1  jruoho 	pfds[1].revents = -1;
    206       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
    207       1.1  jruoho 	    "got: %d", ret);
    208       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
    209       1.1  jruoho 	    pfds[0].revents);
    210       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    211       1.1  jruoho 	    pfds[1].revents);
    212       1.1  jruoho 
    213       1.1  jruoho 	ATF_REQUIRE_EQ(close(fds[0]), 0);
    214       1.1  jruoho 	ATF_REQUIRE_EQ(close(fds[1]), 0);
    215       1.1  jruoho }
    216       1.1  jruoho 
    217       1.1  jruoho ATF_TC(poll_err);
    218       1.1  jruoho ATF_TC_HEAD(poll_err, tc)
    219       1.1  jruoho {
    220       1.1  jruoho 	atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
    221       1.1  jruoho }
    222       1.1  jruoho 
    223       1.1  jruoho ATF_TC_BODY(poll_err, tc)
    224       1.1  jruoho {
    225       1.1  jruoho 	struct pollfd pfd;
    226       1.1  jruoho 	int fd = 0;
    227       1.1  jruoho 
    228       1.1  jruoho 	pfd.fd = fd;
    229       1.1  jruoho 	pfd.events = POLLIN;
    230       1.1  jruoho 
    231       1.1  jruoho 	errno = 0;
    232       1.1  jruoho 	ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
    233       1.1  jruoho 
    234       1.1  jruoho 	errno = 0;
    235       1.1  jruoho 	ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
    236       1.1  jruoho }
    237       1.1  jruoho 
    238       1.1  jruoho ATF_TC(pollts_basic);
    239       1.1  jruoho ATF_TC_HEAD(pollts_basic, tc)
    240       1.1  jruoho {
    241       1.1  jruoho 	atf_tc_set_md_var(tc, "timeout", "10");
    242       1.1  jruoho 	atf_tc_set_md_var(tc, "descr",
    243       1.1  jruoho 	    "Basis functionality test for pollts(2)");
    244       1.1  jruoho }
    245       1.1  jruoho 
    246       1.1  jruoho ATF_TC_BODY(pollts_basic, tc)
    247       1.1  jruoho {
    248       1.1  jruoho 	int fds[2];
    249       1.1  jruoho 	struct pollfd pfds[2];
    250       1.1  jruoho 	struct timespec timeout;
    251       1.1  jruoho 	int ret;
    252       1.1  jruoho 
    253       1.1  jruoho 	ATF_REQUIRE_EQ(pipe(fds), 0);
    254       1.1  jruoho 
    255       1.1  jruoho 	pfds[0].fd = fds[0];
    256       1.1  jruoho 	pfds[0].events = POLLIN;
    257       1.1  jruoho 	pfds[1].fd = fds[1];
    258       1.1  jruoho 	pfds[1].events = POLLOUT;
    259       1.1  jruoho 
    260       1.1  jruoho 	/* Use a timeout of 1 second. */
    261       1.1  jruoho 	timeout.tv_sec = 1;
    262       1.1  jruoho 	timeout.tv_nsec = 0;
    263       1.1  jruoho 
    264       1.1  jruoho 	/*
    265       1.1  jruoho 	 * Check that we get a timeout waiting for data on the read end
    266       1.1  jruoho 	 * of our pipe.
    267       1.1  jruoho 	 */
    268       1.1  jruoho 	pfds[0].revents = -1;
    269       1.1  jruoho 	pfds[1].revents = -1;
    270       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
    271       1.1  jruoho 	    "got: %d", ret);
    272       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    273       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
    274       1.1  jruoho 
    275       1.1  jruoho 	/* Check that the write end of the pipe as reported as ready. */
    276       1.1  jruoho 	pfds[0].revents = -1;
    277       1.1  jruoho 	pfds[1].revents = -1;
    278       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
    279       1.1  jruoho 	    "got: %d", ret);
    280       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
    281       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
    282       1.1  jruoho 	    pfds[1].revents);
    283       1.1  jruoho 
    284       1.1  jruoho 	/* Check that only the write end of the pipe as reported as ready. */
    285       1.1  jruoho 	pfds[0].revents = -1;
    286       1.1  jruoho 	pfds[1].revents = -1;
    287       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
    288       1.1  jruoho 	    "got: %d", ret);
    289       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
    290       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    291       1.1  jruoho 	    pfds[1].revents);
    292       1.1  jruoho 
    293       1.1  jruoho 	/* Write data to our pipe. */
    294       1.1  jruoho 	ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
    295       1.1  jruoho 
    296       1.1  jruoho 	/* Check that both ends of our pipe are reported as ready. */
    297       1.1  jruoho 	pfds[0].revents = -1;
    298       1.1  jruoho 	pfds[1].revents = -1;
    299       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
    300       1.1  jruoho 	    "got: %d", ret);
    301       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
    302       1.1  jruoho 	    pfds[0].revents);
    303       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
    304       1.1  jruoho 	    pfds[1].revents);
    305       1.1  jruoho 
    306       1.1  jruoho 	ATF_REQUIRE_EQ(close(fds[0]), 0);
    307       1.1  jruoho 	ATF_REQUIRE_EQ(close(fds[1]), 0);
    308       1.1  jruoho }
    309       1.1  jruoho 
    310       1.1  jruoho ATF_TC(pollts_err);
    311       1.1  jruoho ATF_TC_HEAD(pollts_err, tc)
    312       1.1  jruoho {
    313       1.1  jruoho 	atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
    314       1.1  jruoho }
    315       1.1  jruoho 
    316       1.1  jruoho ATF_TC_BODY(pollts_err, tc)
    317       1.1  jruoho {
    318       1.1  jruoho 	struct timespec timeout;
    319       1.1  jruoho 	struct pollfd pfd;
    320       1.1  jruoho 	int fd = 0;
    321       1.1  jruoho 
    322       1.1  jruoho 	pfd.fd = fd;
    323       1.1  jruoho 	pfd.events = POLLIN;
    324       1.1  jruoho 
    325       1.1  jruoho 	timeout.tv_sec = 1;
    326       1.1  jruoho 	timeout.tv_nsec = 0;
    327       1.1  jruoho 
    328       1.1  jruoho 	errno = 0;
    329       1.1  jruoho 	ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
    330       1.1  jruoho 
    331       1.1  jruoho 	timeout.tv_sec = -1;
    332       1.1  jruoho 	timeout.tv_nsec = -1;
    333       1.1  jruoho 
    334       1.1  jruoho 	errno = 0;
    335       1.1  jruoho 	ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
    336       1.1  jruoho }
    337       1.1  jruoho 
    338       1.1  jruoho ATF_TC(pollts_sigmask);
    339       1.1  jruoho ATF_TC_HEAD(pollts_sigmask, tc)
    340       1.1  jruoho {
    341       1.1  jruoho 	atf_tc_set_md_var(tc, "timeout", "10");
    342       1.1  jruoho 	atf_tc_set_md_var(tc, "descr",
    343       1.3  jruoho 	    "Check that pollts(2) restores the signal mask (PR kern/44986)");
    344       1.1  jruoho }
    345       1.1  jruoho 
    346       1.1  jruoho ATF_TC_BODY(pollts_sigmask, tc)
    347       1.1  jruoho {
    348       1.1  jruoho 	int fd;
    349       1.1  jruoho 	struct pollfd pfd;
    350       1.1  jruoho 	struct timespec timeout;
    351       1.1  jruoho 	sigset_t mask;
    352       1.1  jruoho 	int ret;
    353       1.1  jruoho 
    354       1.1  jruoho 	fd = open(_PATH_DEVNULL, O_RDONLY);
    355       1.1  jruoho 	ATF_REQUIRE(fd >= 0);
    356       1.1  jruoho 
    357       1.1  jruoho 	pfd.fd = fd;
    358       1.1  jruoho 	pfd.events = POLLIN;
    359       1.1  jruoho 
    360       1.1  jruoho 	/* Use a timeout of 1 second. */
    361       1.1  jruoho 	timeout.tv_sec = 1;
    362       1.1  jruoho 	timeout.tv_nsec = 0;
    363       1.1  jruoho 
    364       1.1  jruoho 	/* Unblock all signals. */
    365       1.1  jruoho 	ATF_REQUIRE_EQ(sigfillset(&mask), 0);
    366       1.1  jruoho 	ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
    367       1.1  jruoho 
    368       1.1  jruoho 	/*
    369       1.1  jruoho 	 * Check that pollts(2) immediately returns. We block *all*
    370       1.1  jruoho 	 * signals during pollts(2).
    371       1.1  jruoho 	 */
    372       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
    373       1.1  jruoho 	    "got: %d", ret);
    374       1.1  jruoho 
    375       1.1  jruoho 	/* Check that signals are now longer blocked. */
    376       1.1  jruoho 	ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
    377       1.1  jruoho 	ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
    378       1.1  jruoho 	    "signal mask was changed.");
    379       1.1  jruoho 
    380       1.1  jruoho 	ATF_REQUIRE_EQ(close(fd), 0);
    381       1.1  jruoho }
    382       1.1  jruoho 
    383  1.3.34.1  martin static const char	fifo_path[] = "pollhup_fifo";
    384  1.3.34.1  martin 
    385  1.3.34.1  martin static void
    386  1.3.34.1  martin fifo_support(void)
    387  1.3.34.1  martin {
    388  1.3.34.1  martin 	errno = 0;
    389  1.3.34.1  martin 	if (mkfifo(fifo_path, 0600) == 0) {
    390  1.3.34.1  martin 		ATF_REQUIRE(unlink(fifo_path) == 0);
    391  1.3.34.1  martin 		return;
    392  1.3.34.1  martin 	}
    393  1.3.34.1  martin 
    394  1.3.34.1  martin 	if (errno == EOPNOTSUPP) {
    395  1.3.34.1  martin 		atf_tc_skip("the kernel does not support FIFOs");
    396  1.3.34.1  martin 	} else {
    397  1.3.34.1  martin 		atf_tc_fail("mkfifo(2) failed");
    398  1.3.34.1  martin 	}
    399  1.3.34.1  martin }
    400  1.3.34.1  martin 
    401  1.3.34.2  martin ATF_TC_WITH_CLEANUP(fifo_inout);
    402  1.3.34.2  martin ATF_TC_HEAD(fifo_inout, tc)
    403  1.3.34.2  martin {
    404  1.3.34.2  martin 	atf_tc_set_md_var(tc, "descr",
    405  1.3.34.2  martin 	    "Check POLLIN/POLLOUT behavior with fifos");
    406  1.3.34.2  martin }
    407  1.3.34.2  martin 
    408  1.3.34.2  martin ATF_TC_BODY(fifo_inout, tc)
    409  1.3.34.2  martin {
    410  1.3.34.2  martin 	struct pollfd pfd[2];
    411  1.3.34.2  martin 	char *buf;
    412  1.3.34.2  martin 	int rfd, wfd;
    413  1.3.34.2  martin 	long pipe_buf;
    414  1.3.34.2  martin 
    415  1.3.34.2  martin 	fifo_support();
    416  1.3.34.2  martin 
    417  1.3.34.2  martin 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
    418  1.3.34.2  martin 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
    419  1.3.34.2  martin 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY | O_NONBLOCK)) >= 0);
    420  1.3.34.2  martin 
    421  1.3.34.2  martin 	/* Get the maximum atomic pipe write size. */
    422  1.3.34.2  martin 	pipe_buf = fpathconf(wfd, _PC_PIPE_BUF);
    423  1.3.34.2  martin 	ATF_REQUIRE(pipe_buf > 1);
    424  1.3.34.2  martin 
    425  1.3.34.2  martin 	buf = malloc(pipe_buf);
    426  1.3.34.2  martin 	ATF_REQUIRE(buf != NULL);
    427  1.3.34.2  martin 
    428  1.3.34.2  martin 	memset(&pfd, 0, sizeof(pfd));
    429  1.3.34.2  martin 	pfd[0].fd = rfd;
    430  1.3.34.2  martin 	pfd[0].events = POLLIN | POLLRDNORM;
    431  1.3.34.2  martin 	pfd[1].fd = wfd;
    432  1.3.34.2  martin 	pfd[1].events = POLLOUT | POLLWRNORM;
    433  1.3.34.2  martin 
    434  1.3.34.2  martin 	/* We expect the FIFO to be writable but not readable. */
    435  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
    436  1.3.34.2  martin 	ATF_REQUIRE(pfd[0].revents == 0);
    437  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
    438  1.3.34.2  martin 
    439  1.3.34.2  martin 	/* Write a single byte of data into the FIFO. */
    440  1.3.34.2  martin 	ATF_REQUIRE(write(wfd, buf, 1) == 1);
    441  1.3.34.2  martin 
    442  1.3.34.2  martin 	/* We expect the FIFO to be readable and writable. */
    443  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) == 2);
    444  1.3.34.2  martin 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
    445  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
    446  1.3.34.2  martin 
    447  1.3.34.2  martin 	/* Read that single byte back out. */
    448  1.3.34.2  martin 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
    449  1.3.34.2  martin 
    450  1.3.34.2  martin 	/*
    451  1.3.34.2  martin 	 * Write data into the FIFO until it is full, which is
    452  1.3.34.2  martin 	 * defined as insufficient buffer space to hold a the
    453  1.3.34.2  martin 	 * maximum atomic pipe write size.
    454  1.3.34.2  martin 	 */
    455  1.3.34.2  martin 	while (write(wfd, buf, pipe_buf) != -1) {
    456  1.3.34.2  martin 		continue;
    457  1.3.34.2  martin 	}
    458  1.3.34.2  martin 	ATF_REQUIRE(errno == EAGAIN);
    459  1.3.34.2  martin 
    460  1.3.34.2  martin 	/* We expect the FIFO to be readble but not writable. */
    461  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
    462  1.3.34.2  martin 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
    463  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == 0);
    464  1.3.34.2  martin 
    465  1.3.34.2  martin 	/* Read a single byte of data from the FIFO. */
    466  1.3.34.2  martin 	ATF_REQUIRE(read(rfd, buf, 1) == 1);
    467  1.3.34.2  martin 
    468  1.3.34.2  martin 	/*
    469  1.3.34.2  martin 	 * Because we have read only a single byte out, there will
    470  1.3.34.2  martin 	 * be insufficient space for a pipe_buf-sized message, so
    471  1.3.34.2  martin 	 * the FIFO should still not be writable.
    472  1.3.34.2  martin 	 */
    473  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
    474  1.3.34.2  martin 	ATF_REQUIRE(pfd[0].revents == (POLLIN | POLLRDNORM));
    475  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == 0);
    476  1.3.34.2  martin 
    477  1.3.34.2  martin 	/*
    478  1.3.34.2  martin 	 * Now read enough so that exactly pipe_buf space should
    479  1.3.34.2  martin 	 * be available.  The FIFO should be writable after that.
    480  1.3.34.2  martin 	 * N.B. we don't care if it's readable at this point.
    481  1.3.34.2  martin 	 */
    482  1.3.34.2  martin 	ATF_REQUIRE(read(rfd, buf, pipe_buf - 1) == pipe_buf - 1);
    483  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) >= 1);
    484  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
    485  1.3.34.2  martin 
    486  1.3.34.2  martin 	/*
    487  1.3.34.2  martin 	 * Now read all of the data out of the FIFO and ensure that
    488  1.3.34.2  martin 	 * we get back to the initial state.
    489  1.3.34.2  martin 	 */
    490  1.3.34.2  martin 	while (read(rfd, buf, pipe_buf) != -1) {
    491  1.3.34.2  martin 		continue;
    492  1.3.34.2  martin 	}
    493  1.3.34.2  martin 	ATF_REQUIRE(errno == EAGAIN);
    494  1.3.34.2  martin 
    495  1.3.34.2  martin 	ATF_REQUIRE(poll(pfd, 2, 0) == 1);
    496  1.3.34.2  martin 	ATF_REQUIRE(pfd[0].revents == 0);
    497  1.3.34.2  martin 	ATF_REQUIRE(pfd[1].revents == (POLLOUT | POLLWRNORM));
    498  1.3.34.2  martin 
    499  1.3.34.2  martin 	(void)close(wfd);
    500  1.3.34.2  martin 	(void)close(rfd);
    501  1.3.34.2  martin }
    502  1.3.34.2  martin 
    503  1.3.34.2  martin ATF_TC_CLEANUP(fifo_inout, tc)
    504  1.3.34.2  martin {
    505  1.3.34.2  martin 	(void)unlink(fifo_path);
    506  1.3.34.2  martin }
    507  1.3.34.2  martin 
    508  1.3.34.1  martin ATF_TC_WITH_CLEANUP(fifo_hup1);
    509  1.3.34.1  martin ATF_TC_HEAD(fifo_hup1, tc)
    510  1.3.34.1  martin {
    511  1.3.34.1  martin 	atf_tc_set_md_var(tc, "descr",
    512  1.3.34.1  martin 	    "Check POLLHUP behavior with fifos [1]");
    513  1.3.34.1  martin }
    514  1.3.34.1  martin 
    515  1.3.34.1  martin ATF_TC_BODY(fifo_hup1, tc)
    516  1.3.34.1  martin {
    517  1.3.34.1  martin 	struct pollfd pfd;
    518  1.3.34.1  martin 	int rfd, wfd;
    519  1.3.34.1  martin 
    520  1.3.34.1  martin 	fifo_support();
    521  1.3.34.1  martin 
    522  1.3.34.1  martin 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
    523  1.3.34.1  martin 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
    524  1.3.34.1  martin 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
    525  1.3.34.1  martin 
    526  1.3.34.1  martin 	memset(&pfd, 0, sizeof(pfd));
    527  1.3.34.1  martin 	pfd.fd = rfd;
    528  1.3.34.1  martin 	pfd.events = POLLIN;
    529  1.3.34.1  martin 
    530  1.3.34.1  martin 	(void)close(wfd);
    531  1.3.34.1  martin 
    532  1.3.34.1  martin 	ATF_REQUIRE(poll(&pfd, 1, 0) == 1);
    533  1.3.34.1  martin 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
    534  1.3.34.2  martin 
    535  1.3.34.2  martin 	/*
    536  1.3.34.2  martin 	 * Check that POLLHUP is cleared when a writer re-connects.
    537  1.3.34.2  martin 	 * Since the writer will not put any data into the FIFO, we
    538  1.3.34.2  martin 	 * expect no events.
    539  1.3.34.2  martin 	 */
    540  1.3.34.2  martin 	memset(&pfd, 0, sizeof(pfd));
    541  1.3.34.2  martin 	pfd.fd = rfd;
    542  1.3.34.2  martin 	pfd.events = POLLIN;
    543  1.3.34.2  martin 
    544  1.3.34.2  martin 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
    545  1.3.34.2  martin 	ATF_REQUIRE(poll(&pfd, 1, 0) == 0);
    546  1.3.34.1  martin }
    547  1.3.34.1  martin 
    548  1.3.34.1  martin ATF_TC_CLEANUP(fifo_hup1, tc)
    549  1.3.34.1  martin {
    550  1.3.34.1  martin 	(void)unlink(fifo_path);
    551  1.3.34.1  martin }
    552  1.3.34.1  martin 
    553  1.3.34.1  martin ATF_TC_WITH_CLEANUP(fifo_hup2);
    554  1.3.34.1  martin ATF_TC_HEAD(fifo_hup2, tc)
    555  1.3.34.1  martin {
    556  1.3.34.1  martin 	atf_tc_set_md_var(tc, "descr",
    557  1.3.34.1  martin 	    "Check POLLHUP behavior with fifos [2]");
    558  1.3.34.1  martin }
    559  1.3.34.1  martin 
    560  1.3.34.1  martin ATF_TC_BODY(fifo_hup2, tc)
    561  1.3.34.1  martin {
    562  1.3.34.1  martin 	struct pollfd pfd;
    563  1.3.34.1  martin 	int rfd, wfd;
    564  1.3.34.1  martin 	pid_t pid;
    565  1.3.34.1  martin 	struct timespec ts1, ts2;
    566  1.3.34.1  martin 
    567  1.3.34.1  martin 	fifo_support();
    568  1.3.34.1  martin 
    569  1.3.34.1  martin 	ATF_REQUIRE(mkfifo(fifo_path, 0600) == 0);
    570  1.3.34.1  martin 	ATF_REQUIRE((rfd = open(fifo_path, O_RDONLY | O_NONBLOCK)) >= 0);
    571  1.3.34.1  martin 	ATF_REQUIRE((wfd = open(fifo_path, O_WRONLY)) >= 0);
    572  1.3.34.1  martin 
    573  1.3.34.1  martin 	memset(&pfd, 0, sizeof(pfd));
    574  1.3.34.1  martin 	pfd.fd = rfd;
    575  1.3.34.1  martin 	pfd.events = POLLIN;
    576  1.3.34.1  martin 
    577  1.3.34.1  martin 	pid = fork();
    578  1.3.34.1  martin 	ATF_REQUIRE(pid >= 0);
    579  1.3.34.1  martin 
    580  1.3.34.1  martin 	if (pid == 0) {
    581  1.3.34.1  martin 		(void)close(rfd);
    582  1.3.34.1  martin 		sleep(5);
    583  1.3.34.1  martin 		(void)close(wfd);
    584  1.3.34.1  martin 		_exit(0);
    585  1.3.34.1  martin 	}
    586  1.3.34.1  martin 	(void)close(wfd);
    587  1.3.34.1  martin 
    588  1.3.34.1  martin 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
    589  1.3.34.1  martin 	ATF_REQUIRE(poll(&pfd, 1, INFTIM) == 1);
    590  1.3.34.1  martin 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
    591  1.3.34.1  martin 
    592  1.3.34.1  martin 	/* Make sure at least a couple of seconds have elapsed. */
    593  1.3.34.1  martin 	ATF_REQUIRE(ts2.tv_sec - ts1.tv_sec >= 2);
    594  1.3.34.1  martin 
    595  1.3.34.1  martin 	ATF_REQUIRE((pfd.revents & POLLHUP) != 0);
    596  1.3.34.1  martin }
    597  1.3.34.1  martin 
    598  1.3.34.1  martin ATF_TC_CLEANUP(fifo_hup2, tc)
    599  1.3.34.1  martin {
    600  1.3.34.1  martin 	(void)unlink(fifo_path);
    601  1.3.34.1  martin }
    602  1.3.34.1  martin 
    603       1.1  jruoho ATF_TP_ADD_TCS(tp)
    604       1.1  jruoho {
    605       1.1  jruoho 
    606       1.2  jruoho 	ATF_TP_ADD_TC(tp, poll_3way);
    607       1.1  jruoho 	ATF_TP_ADD_TC(tp, poll_basic);
    608       1.1  jruoho 	ATF_TP_ADD_TC(tp, poll_err);
    609       1.1  jruoho 	ATF_TP_ADD_TC(tp, pollts_basic);
    610       1.1  jruoho 	ATF_TP_ADD_TC(tp, pollts_err);
    611       1.1  jruoho 	ATF_TP_ADD_TC(tp, pollts_sigmask);
    612       1.1  jruoho 
    613  1.3.34.2  martin 	ATF_TP_ADD_TC(tp, fifo_inout);
    614  1.3.34.1  martin 	ATF_TP_ADD_TC(tp, fifo_hup1);
    615  1.3.34.1  martin 	ATF_TP_ADD_TC(tp, fifo_hup2);
    616  1.3.34.1  martin 
    617       1.1  jruoho 	return atf_no_error();
    618       1.1  jruoho }
    619