1*4c87aefeSPatrick Mooney /*
2*4c87aefeSPatrick Mooney  * This file and its contents are supplied under the terms of the
3*4c87aefeSPatrick Mooney  * Common Development and Distribution License ("CDDL"), version 1.0.
4*4c87aefeSPatrick Mooney  * You may only use this file in accordance with the terms of version
5*4c87aefeSPatrick Mooney  * 1.0 of the CDDL.
6*4c87aefeSPatrick Mooney  *
7*4c87aefeSPatrick Mooney  * A full copy of the text of the CDDL should have accompanied this
8*4c87aefeSPatrick Mooney  * source.  A copy of the CDDL is also available via the Internet at
9*4c87aefeSPatrick Mooney  * http://www.illumos.org/license/CDDL.
10*4c87aefeSPatrick Mooney  */
11*4c87aefeSPatrick Mooney 
12*4c87aefeSPatrick Mooney /*
13*4c87aefeSPatrick Mooney  * Copyright 2018 Joyent, Inc.
14*4c87aefeSPatrick Mooney  */
15*4c87aefeSPatrick Mooney 
16*4c87aefeSPatrick Mooney /*
17*4c87aefeSPatrick Mooney  *        Test:	read.cancel
18*4c87aefeSPatrick Mooney  *   Assertion: A read is not requeued if mevent_disable() is called while it is
19*4c87aefeSPatrick Mooney  *		being handled.
20*4c87aefeSPatrick Mooney  *
21*4c87aefeSPatrick Mooney  *    Strategy: 1. Create a pipe
22*4c87aefeSPatrick Mooney  *		2. Call mevent_add() to be notified of writes to the pipe.  The
23*4c87aefeSPatrick Mooney  *		   callback will signal a cv.
24*4c87aefeSPatrick Mooney  *		3. Write to the pipe then wait for a wakeup.
25*4c87aefeSPatrick Mooney  *		4. From the read event callback, disable the event then awaken
26*4c87aefeSPatrick Mooney  *		   the main thread.
27*4c87aefeSPatrick Mooney  *		5. In the main thread, add a timer event that will awaken the
28*4c87aefeSPatrick Mooney  *		   main thread after a short delay.
29*4c87aefeSPatrick Mooney  *		5. Write to the pipe and wait to be awoken.  The wakeup should
30*4c87aefeSPatrick Mooney  *		   come from the timer event, not the read event.
31*4c87aefeSPatrick Mooney  */
32*4c87aefeSPatrick Mooney 
33*4c87aefeSPatrick Mooney #include <errno.h>
34*4c87aefeSPatrick Mooney #include <fcntl.h>
35*4c87aefeSPatrick Mooney #include <pthread.h>
36*4c87aefeSPatrick Mooney #include <signal.h>
37*4c87aefeSPatrick Mooney #include <stdio.h>
38*4c87aefeSPatrick Mooney #include <stdlib.h>
39*4c87aefeSPatrick Mooney #include <strings.h>
40*4c87aefeSPatrick Mooney #include <unistd.h>
41*4c87aefeSPatrick Mooney 
42*4c87aefeSPatrick Mooney #include <sys/types.h>
43*4c87aefeSPatrick Mooney #include <sys/stat.h>
44*4c87aefeSPatrick Mooney 
45*4c87aefeSPatrick Mooney #include "testlib.h"
46*4c87aefeSPatrick Mooney #include "mevent.h"
47*4c87aefeSPatrick Mooney 
48*4c87aefeSPatrick Mooney typedef enum {
49*4c87aefeSPatrick Mooney 	CB_NONE,
50*4c87aefeSPatrick Mooney 	CB_READ,
51*4c87aefeSPatrick Mooney 	CB_TIMER,
52*4c87aefeSPatrick Mooney } lastwake_t;
53*4c87aefeSPatrick Mooney 
54*4c87aefeSPatrick Mooney static lastwake_t lastwake = CB_NONE;
55*4c87aefeSPatrick Mooney 
56*4c87aefeSPatrick Mooney static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
57*4c87aefeSPatrick Mooney static pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
58*4c87aefeSPatrick Mooney 
59*4c87aefeSPatrick Mooney static struct mevent *read_event;
60*4c87aefeSPatrick Mooney 
61*4c87aefeSPatrick Mooney static void
munch(int fd,enum ev_type ev,void * arg)62*4c87aefeSPatrick Mooney munch(int fd, enum ev_type ev, void *arg)
63*4c87aefeSPatrick Mooney {
64*4c87aefeSPatrick Mooney 	ssize_t nbytes;
65*4c87aefeSPatrick Mooney 	char buf[32] = { 0 };
66*4c87aefeSPatrick Mooney 	int err;
67*4c87aefeSPatrick Mooney 
68*4c87aefeSPatrick Mooney 	if ((nbytes = read(fd, buf, sizeof (buf))) < 0) {
69*4c87aefeSPatrick Mooney 		FAIL_ERRNO("bad read");
70*4c87aefeSPatrick Mooney 	}
71*4c87aefeSPatrick Mooney 	VERBOSE(("read %ld bytes '%s'", nbytes, buf));
72*4c87aefeSPatrick Mooney 
73*4c87aefeSPatrick Mooney 	err = mevent_disable(read_event);
74*4c87aefeSPatrick Mooney 	ASSERT_INT_EQ(("mevent_disable: ", strerror(err)), err, 0);
75*4c87aefeSPatrick Mooney 
76*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&mtx);
77*4c87aefeSPatrick Mooney 
78*4c87aefeSPatrick Mooney 	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_NONE);
79*4c87aefeSPatrick Mooney 	lastwake = CB_READ;
80*4c87aefeSPatrick Mooney 
81*4c87aefeSPatrick Mooney 	pthread_cond_signal(&cv);
82*4c87aefeSPatrick Mooney 	VERBOSE(("wakeup"));
83*4c87aefeSPatrick Mooney 
84*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&mtx);
85*4c87aefeSPatrick Mooney }
86*4c87aefeSPatrick Mooney 
87*4c87aefeSPatrick Mooney static void
tick(int ms,enum ev_type ev,void * arg)88*4c87aefeSPatrick Mooney tick(int ms, enum ev_type ev, void *arg)
89*4c87aefeSPatrick Mooney {
90*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&mtx);
91*4c87aefeSPatrick Mooney 
92*4c87aefeSPatrick Mooney 	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_READ);
93*4c87aefeSPatrick Mooney 	lastwake = CB_TIMER;
94*4c87aefeSPatrick Mooney 
95*4c87aefeSPatrick Mooney 	pthread_cond_signal(&cv);
96*4c87aefeSPatrick Mooney 	VERBOSE(("wakeup"));
97*4c87aefeSPatrick Mooney 
98*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&mtx);
99*4c87aefeSPatrick Mooney }
100*4c87aefeSPatrick Mooney 
101*4c87aefeSPatrick Mooney int
main(int argc,const char * argv[])102*4c87aefeSPatrick Mooney main(int argc, const char *argv[])
103*4c87aefeSPatrick Mooney {
104*4c87aefeSPatrick Mooney 	int pipefds[2];
105*4c87aefeSPatrick Mooney 	struct mevent *timer;
106*4c87aefeSPatrick Mooney 	ssize_t written;
107*4c87aefeSPatrick Mooney 	char *msgs[] = { "first", "second" };
108*4c87aefeSPatrick Mooney 	char *msg;
109*4c87aefeSPatrick Mooney 
110*4c87aefeSPatrick Mooney 	start_test(argv[0], 5);
111*4c87aefeSPatrick Mooney 	start_event_thread();
112*4c87aefeSPatrick Mooney 
113*4c87aefeSPatrick Mooney 	if (pipe(pipefds) != 0) {
114*4c87aefeSPatrick Mooney 		FAIL_ERRNO("pipe");
115*4c87aefeSPatrick Mooney 	}
116*4c87aefeSPatrick Mooney 	if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) != 0) {
117*4c87aefeSPatrick Mooney 		FAIL_ERRNO("set pipe nonblocking");
118*4c87aefeSPatrick Mooney 	}
119*4c87aefeSPatrick Mooney 
120*4c87aefeSPatrick Mooney 	/*
121*4c87aefeSPatrick Mooney 	 * First write
122*4c87aefeSPatrick Mooney 	 */
123*4c87aefeSPatrick Mooney 	msg = msgs[0];
124*4c87aefeSPatrick Mooney 	read_event = mevent_add(pipefds[0], EVF_READ, munch, msg);
125*4c87aefeSPatrick Mooney 	ASSERT_PTR_NEQ(("mevent_add pipefd"), read_event, NULL);
126*4c87aefeSPatrick Mooney 
127*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&mtx);
128*4c87aefeSPatrick Mooney 	written = write(pipefds[1], msg, strlen(msg));
129*4c87aefeSPatrick Mooney 	if (written < 0) {
130*4c87aefeSPatrick Mooney 		FAIL_ERRNO("bad write");
131*4c87aefeSPatrick Mooney 	}
132*4c87aefeSPatrick Mooney 	ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));
133*4c87aefeSPatrick Mooney 
134*4c87aefeSPatrick Mooney 	/*
135*4c87aefeSPatrick Mooney 	 * Wait for it to be read
136*4c87aefeSPatrick Mooney 	 */
137*4c87aefeSPatrick Mooney 	pthread_cond_wait(&cv, &mtx);
138*4c87aefeSPatrick Mooney 	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_READ);
139*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&mtx);
140*4c87aefeSPatrick Mooney 
141*4c87aefeSPatrick Mooney 	/*
142*4c87aefeSPatrick Mooney 	 * Add timer, second write.
143*4c87aefeSPatrick Mooney 	 */
144*4c87aefeSPatrick Mooney 	msg = msgs[1];
145*4c87aefeSPatrick Mooney 	timer = mevent_add(50, EVF_TIMER, tick, msg);
146*4c87aefeSPatrick Mooney 	ASSERT_PTR_NEQ(("mevent_add timer"), timer, NULL);
147*4c87aefeSPatrick Mooney 
148*4c87aefeSPatrick Mooney 	pthread_mutex_lock(&mtx);
149*4c87aefeSPatrick Mooney 	written = write(pipefds[1], msg, strlen(msg));
150*4c87aefeSPatrick Mooney 	if (written < 0) {
151*4c87aefeSPatrick Mooney 		FAIL_ERRNO("bad write");
152*4c87aefeSPatrick Mooney 	}
153*4c87aefeSPatrick Mooney 	ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));
154*4c87aefeSPatrick Mooney 
155*4c87aefeSPatrick Mooney 	/*
156*4c87aefeSPatrick Mooney 	 * Wait for timer to expire
157*4c87aefeSPatrick Mooney 	 */
158*4c87aefeSPatrick Mooney 	pthread_cond_wait(&cv, &mtx);
159*4c87aefeSPatrick Mooney 	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_TIMER);
160*4c87aefeSPatrick Mooney 	pthread_mutex_unlock(&mtx);
161*4c87aefeSPatrick Mooney 
162*4c87aefeSPatrick Mooney 	PASS();
163*4c87aefeSPatrick Mooney }