• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012 Intel Corporation
3  * Copyright © 2013 Jason Ekstrand
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <sys/socket.h>
35 #include <unistd.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/mman.h>
40 
41 #include <pthread.h>
42 #include <poll.h>
43 
44 #include "wayland-private.h"
45 #include "wayland-server.h"
46 #include "wayland-client.h"
47 #include "test-runner.h"
48 #include "test-compositor.h"
49 
50 #include "tests-server-protocol.h"
51 #include "tests-client-protocol.h"
52 
53 struct display_destroy_listener {
54 	struct wl_listener listener;
55 	int done;
56 };
57 
58 static void
display_destroy_notify(struct wl_listener * l,void * data)59 display_destroy_notify(struct wl_listener *l, void *data)
60 {
61 	struct display_destroy_listener *listener;
62 
63 	listener = container_of(l, struct display_destroy_listener, listener);
64 	listener->done = 1;
65 }
66 
TEST(display_destroy_listener)67 TEST(display_destroy_listener)
68 {
69 	struct wl_display *display;
70 	struct display_destroy_listener a, b;
71 
72 	display = wl_display_create();
73 	assert(display);
74 
75 	a.listener.notify = &display_destroy_notify;
76 	a.done = 0;
77 	wl_display_add_destroy_listener(display, &a.listener);
78 
79 	assert(wl_display_get_destroy_listener(display, display_destroy_notify) ==
80 	       &a.listener);
81 
82 	b.listener.notify = display_destroy_notify;
83 	b.done = 0;
84 	wl_display_add_destroy_listener(display, &b.listener);
85 
86 	wl_list_remove(&a.listener.link);
87 
88 	wl_display_destroy(display);
89 
90 	assert(!a.done);
91 	assert(b.done);
92 }
93 
94 /* Fake 'client' which does not use wl_display_connect, and thus leaves the
95  * file descriptor passed through WAYLAND_SOCKET intact. This should not
96  * trigger an assertion in the leak check. */
97 static void
empty_client(void)98 empty_client(void)
99 {
100 	return;
101 }
102 
TEST(tc_leaks_tests)103 TEST(tc_leaks_tests)
104 {
105 	struct display *d = display_create();
106 	client_create_noarg(d, empty_client);
107 	display_run(d);
108 	display_destroy(d);
109 }
110 
111 /* This is how pre proxy-version registry binds worked,
112  * this should create a proxy that shares the display's
113  * version number: 0 */
114 static void *
old_registry_bind(struct wl_registry * wl_registry,uint32_t name,const struct wl_interface * interface,uint32_t version)115 old_registry_bind(struct wl_registry *wl_registry,
116 		  uint32_t name,
117 		  const struct wl_interface *interface,
118 		  uint32_t version)
119 {
120 	struct wl_proxy *id;
121 
122 	id = wl_proxy_marshal_constructor(
123 		(struct wl_proxy *) wl_registry, WL_REGISTRY_BIND,
124 		interface, name, interface->name, version, NULL);
125 
126 	return (void *) id;
127 }
128 
129 struct handler_info {
130 	struct wl_seat *seat;
131 	uint32_t bind_version;
132 	bool use_unversioned;
133 };
134 
135 static void
registry_handle_globals(void * data,struct wl_registry * registry,uint32_t id,const char * intf,uint32_t ver)136 registry_handle_globals(void *data, struct wl_registry *registry,
137 			uint32_t id, const char *intf, uint32_t ver)
138 {
139 	struct handler_info *hi = data;
140 
141 	/* This is only for the proxy version test */
142 	if (hi->bind_version)
143 		ver = hi->bind_version;
144 
145 	if (strcmp(intf, "wl_seat") == 0) {
146 		if (hi->use_unversioned)
147 			hi->seat = old_registry_bind(registry, id,
148 						     &wl_seat_interface, ver);
149 		else
150 			hi->seat = wl_registry_bind(registry, id,
151 						    &wl_seat_interface, ver);
152 		assert(hi->seat);
153 	}
154 }
155 
156 static const struct wl_registry_listener registry_listener = {
157 	registry_handle_globals,
158 	NULL
159 };
160 
161 static struct wl_seat *
client_get_seat_with_info(struct client * c,struct handler_info * hi)162 client_get_seat_with_info(struct client *c, struct handler_info *hi)
163 {
164 	struct wl_registry *reg = wl_display_get_registry(c->wl_display);
165 	assert(reg);
166 
167 	assert(hi);
168 	hi->seat = NULL;
169 	wl_registry_add_listener(reg, &registry_listener, hi);
170 	wl_display_roundtrip(c->wl_display);
171 	assert(hi->seat);
172 
173 	wl_registry_destroy(reg);
174 
175 	return hi->seat;
176 }
177 
178 static struct wl_seat *
client_get_seat(struct client * c)179 client_get_seat(struct client *c)
180 {
181 	struct handler_info hi;
182 
183 	hi.use_unversioned = false;
184 	hi.bind_version = 0;
185 
186 	return client_get_seat_with_info(c, &hi);
187 }
188 
189 static void
check_pending_error(struct client * c,struct wl_proxy * proxy)190 check_pending_error(struct client *c, struct wl_proxy *proxy)
191 {
192 	uint32_t ec, id;
193 	int err;
194 	const struct wl_interface *intf;
195 
196 	err = wl_display_get_error(c->wl_display);
197 	assert(err == EPROTO);
198 
199 	ec = wl_display_get_protocol_error(c->wl_display, &intf, &id);
200 	assert(ec == 23);
201 	assert(intf == &wl_seat_interface);
202 	assert(id == wl_proxy_get_id(proxy));
203 }
204 
205 static void
check_for_error(struct client * c,struct wl_proxy * proxy)206 check_for_error(struct client *c, struct wl_proxy *proxy)
207 {
208 	/* client should be disconnected */
209 	assert(wl_display_roundtrip(c->wl_display) == -1);
210 
211 	check_pending_error(c, proxy);
212 }
213 
214 static struct client_info *
find_client_info(struct display * d,struct wl_client * client)215 find_client_info(struct display *d, struct wl_client *client)
216 {
217 	struct client_info *ci;
218 
219 	wl_list_for_each(ci, &d->clients, link) {
220 		if (ci->wl_client == client)
221 			return ci;
222 	}
223 
224 	return NULL;
225 }
226 
227 static void
bind_seat(struct wl_client * client,void * data,uint32_t vers,uint32_t id)228 bind_seat(struct wl_client *client, void *data,
229 	  uint32_t vers, uint32_t id)
230 {
231 	struct display *d = data;
232 	struct client_info *ci;
233 	struct wl_resource *res;
234 
235 	ci = find_client_info(d, client);
236 	assert(ci);
237 
238 	res = wl_resource_create(client, &wl_seat_interface, vers, id);
239 	assert(res);
240 
241 	/* save the resource as client's info data,
242 	 * so that we can use it later */
243 	ci->data = res;
244 }
245 
246 static void
client_disconnect_nocheck(struct client * c)247 client_disconnect_nocheck(struct client *c)
248 {
249 	wl_proxy_destroy((struct wl_proxy *) c->tc);
250 	wl_display_disconnect(c->wl_display);
251 	free(c);
252 }
253 
254 static void
post_error_main(void)255 post_error_main(void)
256 {
257 	struct client *c = client_connect();
258 	struct wl_seat *seat = client_get_seat(c);
259 
260 	/* stop display so that it can post the error.
261 	 * The function should return -1, because of the posted error */
262 	assert(stop_display(c, 1) == -1);
263 
264 	/* display should have posted error, check it! */
265 	check_for_error(c, (struct wl_proxy *) seat);
266 
267 	/* don't call client_disconnect(c), because then the test would be
268 	 * aborted due to checks for error in this function */
269 	wl_proxy_destroy((struct wl_proxy *) seat);
270 	client_disconnect_nocheck(c);
271 }
272 
TEST(post_error_to_one_client)273 TEST(post_error_to_one_client)
274 {
275 	struct display *d = display_create();
276 	struct client_info *cl;
277 
278 	wl_global_create(d->wl_display, &wl_seat_interface,
279 			 1, d, bind_seat);
280 
281 	cl = client_create_noarg(d, post_error_main);
282 	display_run(d);
283 
284 	/* the display was stopped by client, so it can
285 	 * proceed in the code and post an error */
286 	assert(cl->data);
287 	wl_resource_post_error((struct wl_resource *) cl->data,
288 			       23, "Dummy error");
289 
290 	/* this one should be ignored */
291 	wl_resource_post_error((struct wl_resource *) cl->data,
292 			       21, "Dummy error (ignore)");
293 
294 	display_resume(d);
295 	display_destroy(d);
296 }
297 
298 static void
post_error_main2(void)299 post_error_main2(void)
300 {
301 	struct client *c = client_connect();
302 	struct wl_seat *seat = client_get_seat(c);
303 
304 	/* the error should not be posted for this client */
305 	assert(stop_display(c, 2) >= 0);
306 
307 	wl_proxy_destroy((struct wl_proxy *) seat);
308 	client_disconnect(c);
309 }
310 
311 static void
post_error_main3(void)312 post_error_main3(void)
313 {
314 	struct client *c = client_connect();
315 	struct wl_seat *seat = client_get_seat(c);
316 
317 	assert(stop_display(c, 2) == -1);
318 	check_for_error(c, (struct wl_proxy *) seat);
319 
320 	/* don't call client_disconnect(c), because then the test would be
321 	 * aborted due to checks for error in this function */
322 	wl_proxy_destroy((struct wl_proxy *) seat);
323 	client_disconnect_nocheck(c);
324 }
325 
326 /* all the testcases could be in one TEST, but splitting it
327  * apart is better for debugging when the test fails */
TEST(post_error_to_one_from_two_clients)328 TEST(post_error_to_one_from_two_clients)
329 {
330 	struct display *d = display_create();
331 	struct client_info *cl;
332 
333 	wl_global_create(d->wl_display, &wl_seat_interface,
334 			 1, d, bind_seat);
335 
336 	client_create_noarg(d, post_error_main2);
337 	cl = client_create_noarg(d, post_error_main3);
338 	display_run(d);
339 
340 	/* post error only to the second client */
341 	assert(cl->data);
342 	wl_resource_post_error((struct wl_resource *) cl->data,
343 			       23, "Dummy error");
344 	wl_resource_post_error((struct wl_resource *) cl->data,
345 			       21, "Dummy error (ignore)");
346 
347 	display_resume(d);
348 	display_destroy(d);
349 }
350 
351 /* all the testcases could be in one TEST, but splitting it
352  * apart is better for debugging when the test fails */
TEST(post_error_to_two_clients)353 TEST(post_error_to_two_clients)
354 {
355 	struct display *d = display_create();
356 	struct client_info *cl, *cl2;
357 
358 	wl_global_create(d->wl_display, &wl_seat_interface,
359 			 1, d, bind_seat);
360 
361 	cl = client_create_noarg(d, post_error_main3);
362 	cl2 = client_create_noarg(d, post_error_main3);
363 
364 	display_run(d);
365 
366 	/* Try to send the error to both clients */
367 	assert(cl->data && cl2->data);
368 	wl_resource_post_error((struct wl_resource *) cl->data,
369 			       23, "Dummy error");
370 	wl_resource_post_error((struct wl_resource *) cl->data,
371 			       21, "Dummy error (ignore)");
372 
373 	wl_resource_post_error((struct wl_resource *) cl2->data,
374 			       23, "Dummy error");
375 	wl_resource_post_error((struct wl_resource *) cl2->data,
376 			       21, "Dummy error (ignore)");
377 
378 	display_resume(d);
379 	display_destroy(d);
380 }
381 
382 static void
post_nomem_main(void)383 post_nomem_main(void)
384 {
385 	struct client *c = client_connect();
386 	struct wl_seat *seat = client_get_seat(c);
387 
388 	assert(stop_display(c, 1) == -1);
389 	assert(wl_display_get_error(c->wl_display) == ENOMEM);
390 
391 	wl_proxy_destroy((struct wl_proxy *) seat);
392 	client_disconnect_nocheck(c);
393 }
394 
TEST(post_nomem_tst)395 TEST(post_nomem_tst)
396 {
397 	struct display *d = display_create();
398 	struct client_info *cl;
399 
400 	wl_global_create(d->wl_display, &wl_seat_interface,
401 			 1, d, bind_seat);
402 
403 	cl = client_create_noarg(d, post_nomem_main);
404 	display_run(d);
405 
406 	assert(cl->data);
407 	wl_resource_post_no_memory((struct wl_resource *) cl->data);
408 	display_resume(d);
409 
410 	/* first client terminated. Run it again,
411 	 * but post no memory to client */
412 	cl = client_create_noarg(d, post_nomem_main);
413 	display_run(d);
414 
415 	assert(cl->data);
416 	wl_client_post_no_memory(cl->wl_client);
417 	display_resume(d);
418 
419 	display_destroy(d);
420 }
421 
422 static void
post_implementation_error_main(void)423 post_implementation_error_main(void)
424 {
425 	struct client *c = client_connect();
426 	struct wl_seat *seat = client_get_seat(c);
427 	uint32_t object_id, protocol_error;
428 	const struct wl_interface *interface;
429 
430 	assert(stop_display(c, 1) == -1);
431 	int err = wl_display_get_error(c->wl_display);
432 	fprintf(stderr, "Err is %i\n", err);
433 	assert(err == EPROTO);
434 	protocol_error = wl_display_get_protocol_error(c->wl_display,
435 						       &interface,
436 						       &object_id);
437 	assert(protocol_error == WL_DISPLAY_ERROR_IMPLEMENTATION);
438 	assert(interface == &wl_display_interface);
439 
440 	wl_proxy_destroy((struct wl_proxy *) seat);
441 	client_disconnect_nocheck(c);
442 }
443 
TEST(post_internal_error_tst)444 TEST(post_internal_error_tst)
445 {
446 	struct display *d = display_create();
447 	struct client_info *cl;
448 
449 	wl_global_create(d->wl_display, &wl_seat_interface,
450 			 1, d, bind_seat);
451 
452 	cl = client_create_noarg(d, post_implementation_error_main);
453 	display_run(d);
454 
455 	wl_client_post_implementation_error(cl->wl_client, "Error %i", 20);
456 
457 	display_resume(d);
458 
459 	display_destroy(d);
460 }
461 
462 static void
register_reading(struct wl_display * display)463 register_reading(struct wl_display *display)
464 {
465 	while(wl_display_prepare_read(display) != 0 && errno == EAGAIN)
466 		assert(wl_display_dispatch_pending(display) >= 0);
467 	assert(wl_display_flush(display) >= 0);
468 }
469 
470 /* create thread that will call prepare+read so that
471  * it will block */
472 static pthread_t
create_thread(struct client * c,void * (* func)(void *))473 create_thread(struct client *c, void *(*func)(void*))
474 {
475 	pthread_t thread;
476 
477 	c->display_stopped = 0;
478 	/* func must set display->stopped to 1 before sleeping */
479 	assert(pthread_create(&thread, NULL, func, c) == 0);
480 
481 	/* make sure the thread is sleeping. It's a little bit racy
482 	 * (setting display_stopped to 1 and calling wl_display_read_events)
483 	 * so call usleep once again after the loop ends - it should
484 	 * be sufficient... */
485 	while (c->display_stopped == 0)
486 		test_usleep(500);
487 	test_usleep(10000);
488 
489 	return thread;
490 }
491 
492 static void *
thread_read_error(void * data)493 thread_read_error(void *data)
494 {
495 	struct client *c = data;
496 
497 	register_reading(c->wl_display);
498 
499 	/*
500 	 * Calling the read right now will block this thread
501 	 * until the other thread will read the data.
502 	 * However, after invoking an error, this
503 	 * thread should be woken up or it will block indefinitely.
504 	 */
505 	c->display_stopped = 1;
506 	assert(wl_display_read_events(c->wl_display) == -1);
507 
508 	assert(wl_display_dispatch_pending(c->wl_display) == -1);
509 	assert(wl_display_get_error(c->wl_display));
510 
511 	pthread_exit(NULL);
512 }
513 
514 /* test posting an error in multi-threaded environment. */
515 static void
threading_post_err(void)516 threading_post_err(void)
517 {
518 	DISABLE_LEAK_CHECKS;
519 
520 	struct client *c = client_connect();
521 	pthread_t thread;
522 
523 	/* register read intention */
524 	register_reading(c->wl_display);
525 
526 	/* use this var as an indicator that thread is sleeping */
527 	c->display_stopped = 0;
528 
529 	/* create new thread that will register its intention too */
530 	thread = create_thread(c, thread_read_error);
531 
532 	/* so now we have sleeping thread waiting for a pthread_cond signal.
533 	 * The main thread must call wl_display_read_events().
534 	 * If this call fails, then it won't call broadcast at the
535 	 * end of the function and the sleeping thread will block indefinitely.
536 	 * Make the call fail and watch if libwayland will unblock the thread! */
537 
538 	/* create error on fd, so that wl_display_read_events will fail.
539 	 * The same can happen when server hangs up */
540 	close(wl_display_get_fd(c->wl_display));
541 	/* this read events will fail and will
542 	 * post an error that should wake the sleeping thread
543 	 * and dispatch the incoming events */
544 	assert(wl_display_read_events(c->wl_display) == -1);
545 
546 	/* kill test in 3 seconds. This should be enough time for the
547 	 * thread to exit if it's not blocking. If everything is OK, than
548 	 * the thread was woken up and the test will end before the SIGALRM */
549 	test_set_timeout(3);
550 	pthread_join(thread, NULL);
551 
552 	client_disconnect_nocheck(c);
553 }
554 
TEST(threading_errors_tst)555 TEST(threading_errors_tst)
556 {
557 	struct display *d = display_create();
558 
559 	client_create_noarg(d, threading_post_err);
560 	display_run(d);
561 
562 	display_destroy(d);
563 }
564 
565 static void *
thread_prepare_and_read(void * data)566 thread_prepare_and_read(void *data)
567 {
568 	struct client *c = data;
569 
570 	register_reading(c->wl_display);
571 
572 	c->display_stopped = 1;
573 
574 	assert(wl_display_read_events(c->wl_display) == 0);
575 	assert(wl_display_dispatch_pending(c->wl_display) == 0);
576 
577 	pthread_exit(NULL);
578 }
579 
580 /* test cancel read*/
581 static void
threading_cancel_read(void)582 threading_cancel_read(void)
583 {
584 	DISABLE_LEAK_CHECKS;
585 
586 	struct client *c = client_connect();
587 	pthread_t th1, th2, th3;
588 
589 	register_reading(c->wl_display);
590 
591 	th1 = create_thread(c, thread_prepare_and_read);
592 	th2 = create_thread(c, thread_prepare_and_read);
593 	th3 = create_thread(c, thread_prepare_and_read);
594 
595 	/* all the threads are sleeping, waiting until read or cancel
596 	 * is called. Cancel the read and let the threads proceed */
597 	wl_display_cancel_read(c->wl_display);
598 
599 	/* kill test in 3 seconds. This should be enough time for the
600 	 * thread to exit if it's not blocking. If everything is OK, than
601 	 * the thread was woken up and the test will end before the SIGALRM */
602 	test_set_timeout(3);
603 	pthread_join(th1, NULL);
604 	pthread_join(th2, NULL);
605 	pthread_join(th3, NULL);
606 
607 	client_disconnect(c);
608 }
609 
TEST(threading_cancel_read_tst)610 TEST(threading_cancel_read_tst)
611 {
612 	struct display *d = display_create();
613 
614 	client_create_noarg(d, threading_cancel_read);
615 	display_run(d);
616 
617 	display_destroy(d);
618 }
619 
620 static void
threading_read_eagain(void)621 threading_read_eagain(void)
622 {
623 	DISABLE_LEAK_CHECKS;
624 
625 	struct client *c = client_connect();
626 	pthread_t th1, th2, th3;
627 
628 	register_reading(c->wl_display);
629 
630 	th1 = create_thread(c, thread_prepare_and_read);
631 	th2 = create_thread(c, thread_prepare_and_read);
632 	th3 = create_thread(c, thread_prepare_and_read);
633 
634 	/* All the threads are sleeping, waiting until read or cancel
635 	 * is called. Since we have no data on socket waiting,
636 	 * the wl_connection_read should end up with error and set errno
637 	 * to EAGAIN. Check if the threads are woken up in this case. */
638 	assert(wl_display_read_events(c->wl_display) == 0);
639 	/* errno should be still set to EAGAIN if wl_connection_read
640 	 * set it - check if we're testing the right case */
641 	assert(errno == EAGAIN);
642 
643 	test_set_timeout(3);
644 	pthread_join(th1, NULL);
645 	pthread_join(th2, NULL);
646 	pthread_join(th3, NULL);
647 
648 	client_disconnect(c);
649 }
650 
TEST(threading_read_eagain_tst)651 TEST(threading_read_eagain_tst)
652 {
653 	struct display *d = display_create();
654 	client_create_noarg(d, threading_read_eagain);
655 
656 	display_run(d);
657 
658 	display_destroy(d);
659 }
660 
661 static void *
thread_prepare_and_read2(void * data)662 thread_prepare_and_read2(void *data)
663 {
664 	struct client *c = data;
665 
666 	while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
667 		assert(wl_display_dispatch_pending(c->wl_display) == -1);
668 	assert(wl_display_flush(c->wl_display) == -1);
669 
670 	c->display_stopped = 1;
671 
672 	assert(wl_display_read_events(c->wl_display) == -1);
673 	assert(wl_display_dispatch_pending(c->wl_display) == -1);
674 
675 	pthread_exit(NULL);
676 }
677 
678 static void
threading_read_after_error(void)679 threading_read_after_error(void)
680 {
681 	DISABLE_LEAK_CHECKS;
682 
683 	struct client *c = client_connect();
684 	pthread_t thread;
685 
686 	/* create an error */
687 	close(wl_display_get_fd(c->wl_display));
688 	assert(wl_display_dispatch(c->wl_display) == -1);
689 
690 	/* try to prepare for reading */
691 	while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
692 		assert(wl_display_dispatch_pending(c->wl_display) == -1);
693 	assert(wl_display_flush(c->wl_display) == -1);
694 
695 	assert(pthread_create(&thread, NULL,
696 			      thread_prepare_and_read2, c) == 0);
697 
698 	/* make sure thread is sleeping */
699 	while (c->display_stopped == 0)
700 		test_usleep(500);
701 	test_usleep(10000);
702 
703 	assert(wl_display_read_events(c->wl_display) == -1);
704 
705 	/* kill test in 3 seconds */
706 	test_set_timeout(3);
707 	pthread_join(thread, NULL);
708 
709 	client_disconnect_nocheck(c);
710 }
711 
TEST(threading_read_after_error_tst)712 TEST(threading_read_after_error_tst)
713 {
714 	struct display *d = display_create();
715 
716 	client_create_noarg(d, threading_read_after_error);
717 	display_run(d);
718 
719 	display_destroy(d);
720 }
721 
722 static void
wait_for_error_using_dispatch(struct client * c,struct wl_proxy * proxy)723 wait_for_error_using_dispatch(struct client *c, struct wl_proxy *proxy)
724 {
725 	int ret;
726 
727 	while (true) {
728 		/* Dispatching should eventually hit the protocol error before
729 		 * any other error. */
730 		ret = wl_display_dispatch(c->wl_display);
731 		if (ret == 0) {
732 			continue;
733 		} else {
734 			assert(errno == EPROTO);
735 			break;
736 		}
737 	}
738 
739 	check_pending_error(c, proxy);
740 }
741 
742 static void
wait_for_error_using_prepare_read(struct client * c,struct wl_proxy * proxy)743 wait_for_error_using_prepare_read(struct client *c, struct wl_proxy *proxy)
744 {
745 	int ret = 0;
746 	struct pollfd pfd[2];
747 
748 	while (true) {
749 		while (wl_display_prepare_read(c->wl_display) != 0 &&
750 		      errno == EAGAIN) {
751 			assert(wl_display_dispatch_pending(c->wl_display) >= 0);
752 		}
753 
754 		/* Flush may fail due to EPIPE if the connection is broken, but
755 		 * this must not set a fatal display error because that would
756 		 * result in it being impossible to read a potential protocol
757 		 * error. */
758 		do {
759 			ret = wl_display_flush(c->wl_display);
760 		} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
761 		assert(ret >= 0 || errno == EPIPE);
762 		assert(wl_display_get_error(c->wl_display) == 0);
763 
764 		pfd[0].fd = wl_display_get_fd(c->wl_display);
765 		pfd[0].events = POLLIN;
766 		do {
767 			ret = poll(pfd, 1, -1);
768 		} while (ret == -1 && errno == EINTR);
769 		assert(ret != -1);
770 
771 		/* We should always manage to read the error before the EPIPE
772 		 * comes this way. */
773 		assert(wl_display_read_events(c->wl_display) == 0);
774 
775 		/* Dispatching should eventually hit the protocol error before
776 		 * any other error. */
777 		ret = wl_display_dispatch_pending(c->wl_display);
778 		if (ret == 0) {
779 			continue;
780 		} else {
781 			assert(errno == EPROTO);
782 			break;
783 		}
784 	}
785 
786 	check_pending_error(c, proxy);
787 }
788 
789 static void
check_error_after_epipe(void * data)790 check_error_after_epipe(void *data)
791 {
792 	bool use_dispatch_helpers = *(bool *) data;
793 	struct client *client;
794 	struct wl_seat *seat;
795 	struct wl_callback *callback;
796 
797 	client = client_connect();
798 
799 	/* This will, according to the implementation below, cause the server
800 	 * to post an error. */
801 	seat = client_get_seat(client);
802 	wl_display_flush(client->wl_display);
803 
804 	/* The server will not actually destroy the client until it receives
805 	 * input, so send something to trigger the client destruction. */
806 	callback = wl_display_sync(client->wl_display);
807 	wl_callback_destroy(callback);
808 
809 	/* Sleep some to give the server a chance to react and destroy the
810 	 * client. */
811 	test_usleep(200000);
812 
813 	/* Wait for the protocol error and check that we reached it before
814 	 * EPIPE. */
815 	if (use_dispatch_helpers) {
816 		wait_for_error_using_dispatch(client, (struct wl_proxy *) seat);
817 	} else {
818 		wait_for_error_using_prepare_read(client,
819 						  (struct wl_proxy *) seat);
820 	}
821 
822 	wl_seat_destroy(seat);
823 	client_disconnect_nocheck(client);
824 }
825 
826 static void
bind_seat_and_post_error(struct wl_client * client,void * data,uint32_t version,uint32_t id)827 bind_seat_and_post_error(struct wl_client *client, void *data,
828 			 uint32_t version, uint32_t id)
829 {
830 	struct display *d = data;
831 	struct client_info *ci;
832 	struct wl_resource *resource;
833 
834 	ci = find_client_info(d, client);
835 	assert(ci);
836 
837 	resource = wl_resource_create(client, &wl_seat_interface, version, id);
838 	assert(resource);
839 	ci->data = resource;
840 
841 	wl_resource_post_error(ci->data, 23, "Dummy error");
842 }
843 
TEST(error_code_after_epipe)844 TEST(error_code_after_epipe)
845 {
846 	struct display *d = display_create();
847 	bool use_dispatch_helpers;
848 
849 	wl_global_create(d->wl_display, &wl_seat_interface,
850 			 1, d, bind_seat_and_post_error);
851 
852 	use_dispatch_helpers = true;
853 	client_create(d, check_error_after_epipe, &use_dispatch_helpers);
854 	display_run(d);
855 
856 	use_dispatch_helpers = false;
857 	client_create(d, check_error_after_epipe, &use_dispatch_helpers);
858 	display_run(d);
859 
860 	display_destroy(d);
861 }
862 
863 static void
check_seat_versions(struct wl_seat * seat,uint32_t ev)864 check_seat_versions(struct wl_seat *seat, uint32_t ev)
865 {
866 	struct wl_pointer *pointer;
867 
868 	assert(wl_proxy_get_version((struct wl_proxy *) seat) == ev);
869 	assert(wl_seat_get_version(seat) == ev);
870 
871 	pointer = wl_seat_get_pointer(seat);
872 	assert(wl_pointer_get_version(pointer) == ev);
873 	assert(wl_proxy_get_version((struct wl_proxy *) pointer) == ev);
874 	wl_proxy_destroy((struct wl_proxy *) pointer);
875 }
876 
877 /* Normal client with proxy versions available. */
878 static void
seat_version(void * data)879 seat_version(void *data)
880 {
881 	struct handler_info *hi = data;
882 	struct client *c = client_connect();
883 	struct wl_seat *seat;
884 
885 	/* display proxy should always be version 0 */
886 	assert(wl_proxy_get_version((struct wl_proxy *) c->wl_display) == 0);
887 
888 	seat = client_get_seat_with_info(c, hi);
889 	if (hi->use_unversioned)
890 		check_seat_versions(seat, 0);
891 	else
892 		check_seat_versions(seat, hi->bind_version);
893 
894 	wl_proxy_destroy((struct wl_proxy *) seat);
895 
896 	client_disconnect_nocheck(c);
897 }
898 
TEST(versions)899 TEST(versions)
900 {
901 	struct display *d = display_create();
902 	struct wl_global *global;
903 	int i;
904 
905 	global = wl_global_create(d->wl_display, &wl_seat_interface,
906 				  5, d, bind_seat);
907 
908 	for (i = 1; i <= 5; i++) {
909 		struct handler_info hi;
910 
911 		hi.bind_version = i;
912 		hi.use_unversioned = false;
913 		client_create(d, seat_version, &hi);
914 		hi.use_unversioned = true;
915 		client_create(d, seat_version, &hi);
916 	}
917 
918 	display_run(d);
919 
920 	wl_global_destroy(global);
921 
922 	display_destroy(d);
923 }
924 
925 static void
check_error_on_destroyed_object(void * data)926 check_error_on_destroyed_object(void *data)
927 {
928 	struct client *c;
929 	struct wl_seat *seat;
930 	uint32_t id;
931 	const struct wl_interface *intf;
932 
933 	c = client_connect();
934 	seat = client_get_seat(c);
935 
936 	/* destroy the seat proxy. The display won't know
937 	 * about it yet, so it will post the error as usual */
938 	wl_proxy_destroy((struct wl_proxy *) seat);
939 
940 	/* let display post the error. The error will
941 	 * be caught in stop_display while dispatching */
942 	assert(stop_display(c, 1) == -1);
943 
944 	/* check the returned error. Since the object was destroyed,
945 	 * we don't know the interface and id */
946 	assert(wl_display_get_error(c->wl_display) == EPROTO);
947 	assert(wl_display_get_protocol_error(c->wl_display, &intf, &id) == 23);
948 	assert(intf == NULL);
949 	assert(id == 0);
950 
951 	client_disconnect_nocheck(c);
952 }
953 
TEST(error_on_destroyed_object)954 TEST(error_on_destroyed_object)
955 {
956 	struct client_info *cl;
957 	struct display *d = display_create();
958 
959 	wl_global_create(d->wl_display, &wl_seat_interface,
960 			 1, d, bind_seat);
961 
962 	cl = client_create_noarg(d, check_error_on_destroyed_object);
963 	display_run(d);
964 
965 	/* did client bind to the seat? */
966 	assert(cl->data);
967 
968 	/* post error on the destroyed object */
969 	wl_resource_post_error((struct wl_resource *) cl->data,
970 			       23, "Dummy error");
971 	display_resume(d);
972 	display_destroy(d);
973 }
974 
975 static bool
global_filter(const struct wl_client * client,const struct wl_global * global,void * data)976 global_filter(const struct wl_client *client,
977 	      const struct wl_global *global,
978 	      void *data)
979 {
980 	/* Hide the wl_data_offer interface if no data was provided */
981 	if (wl_global_get_interface(global) == &wl_data_offer_interface)
982 		return data != NULL;
983 
984 	/* Show all the others */
985 	return true;
986 }
987 
988 static void
bind_data_offer(struct wl_client * client,void * data,uint32_t vers,uint32_t id)989 bind_data_offer(struct wl_client *client, void *data,
990 		uint32_t vers, uint32_t id)
991 {
992 	/* Client should not be able to bind to this interface! */
993 	assert(false);
994 }
995 
996 static void
registry_handle_filtered(void * data,struct wl_registry * registry,uint32_t id,const char * intf,uint32_t ver)997 registry_handle_filtered(void *data, struct wl_registry *registry,
998 			 uint32_t id, const char *intf, uint32_t ver)
999 {
1000 	uint32_t *name = data;
1001 
1002 	if (strcmp (intf, "wl_data_offer") == 0) {
1003 		assert(name);
1004 		*name = id;
1005 	}
1006 }
1007 
1008 static const struct wl_registry_listener registry_listener_filtered = {
1009 	registry_handle_filtered,
1010 	NULL
1011 };
1012 
1013 static void
get_globals(void * data)1014 get_globals(void *data)
1015 {
1016 	struct client *c = client_connect();
1017 	struct wl_registry *registry;
1018 
1019 	registry = wl_display_get_registry(c->wl_display);
1020 	wl_registry_add_listener(registry, &registry_listener_filtered, data);
1021 	wl_display_roundtrip(c->wl_display);
1022 
1023 	wl_registry_destroy(registry);
1024 	client_disconnect_nocheck(c);
1025 }
1026 
TEST(filtered_global_is_hidden)1027 TEST(filtered_global_is_hidden)
1028 {
1029 	struct display *d;
1030 	struct wl_global *g;
1031 
1032 	d = display_create();
1033 
1034 	g = wl_global_create(d->wl_display, &wl_data_offer_interface,
1035 		      1, d, bind_data_offer);
1036 	wl_display_set_global_filter(d->wl_display, global_filter, NULL);
1037 
1038 	client_create_noarg(d, get_globals);
1039 	display_run(d);
1040 
1041 	wl_global_destroy(g);
1042 
1043 	display_destroy(d);
1044 }
1045 
1046 static void
check_bind_error(struct client * c)1047 check_bind_error(struct client *c)
1048 {
1049 	uint32_t errorcode, id;
1050 	int err;
1051 	const struct wl_interface *intf;
1052 
1053 	err = wl_display_get_error(c->wl_display);
1054 	assert(err == EPROTO);
1055 
1056 	errorcode = wl_display_get_protocol_error(c->wl_display, &intf, &id);
1057 	assert(errorcode == WL_DISPLAY_ERROR_INVALID_OBJECT);
1058 }
1059 
1060 static void
force_bind(void * data)1061 force_bind(void *data)
1062 {
1063 	struct client *c = client_connect();
1064 	struct wl_registry *registry;
1065 	void *ptr;
1066 	uint32_t *name = data;
1067 
1068 	registry = wl_display_get_registry(c->wl_display);
1069 
1070 	ptr = wl_registry_bind (registry, *name, &wl_data_offer_interface, 1);
1071 	wl_display_roundtrip(c->wl_display);
1072 	check_bind_error(c);
1073 
1074 	wl_proxy_destroy((struct wl_proxy *) ptr);
1075 	wl_registry_destroy(registry);
1076 
1077 	client_disconnect_nocheck(c);
1078 }
1079 
TEST(bind_fails_on_filtered_global)1080 TEST(bind_fails_on_filtered_global)
1081 {
1082 	struct display *d;
1083 	struct wl_global *g;
1084 	uint32_t *name;
1085 
1086 	/* Create a anonymous shared memory to pass the interface name */
1087 	name = mmap(NULL, sizeof(uint32_t),
1088 		    PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
1089 
1090 	d = display_create();
1091 
1092 	g = wl_global_create(d->wl_display, &wl_data_offer_interface,
1093 			     1, d, bind_data_offer);
1094 	wl_display_set_global_filter(d->wl_display, global_filter, name);
1095 
1096 	client_create(d, get_globals, name);
1097 	*name = 0;
1098 
1099 	display_run(d);
1100 	/* wl_data_offer should be 2 */
1101 	assert(*name == 2);
1102 	wl_display_set_global_filter(d->wl_display, global_filter, NULL);
1103 
1104 	/* Try to bind to the interface name when a global filter is in place */
1105 	client_create(d, force_bind, name);
1106 	display_run(d);
1107 
1108 	wl_global_destroy(g);
1109 
1110 	display_destroy(d);
1111 }
1112 
1113 static void
pre_fd(void * data,struct fd_passer * fdp)1114 pre_fd(void *data, struct fd_passer *fdp)
1115 {
1116 	fd_passer_destroy(fdp);
1117 }
1118 
1119 static void
fd(void * data,struct fd_passer * fdp,int32_t fd)1120 fd(void *data, struct fd_passer *fdp, int32_t fd)
1121 {
1122 	/* We destroyed the resource before this event */
1123 	assert(false);
1124 }
1125 
1126 struct fd_passer_listener fd_passer_listener = {
1127 	pre_fd,
1128 	fd,
1129 };
1130 
1131 static void
zombie_fd_handle_globals(void * data,struct wl_registry * registry,uint32_t id,const char * intf,uint32_t ver)1132 zombie_fd_handle_globals(void *data, struct wl_registry *registry,
1133 			 uint32_t id, const char *intf, uint32_t ver)
1134 {
1135 	struct fd_passer *fdp;
1136 
1137 	if (!strcmp(intf, "fd_passer")) {
1138 		fdp = wl_registry_bind(registry, id, &fd_passer_interface, 1);
1139 		fd_passer_add_listener(fdp, &fd_passer_listener, NULL);
1140 	}
1141 }
1142 
1143 static const struct wl_registry_listener zombie_fd_registry_listener = {
1144 	zombie_fd_handle_globals,
1145 	NULL
1146 };
1147 
1148 static void
zombie_client(void * data)1149 zombie_client(void *data)
1150 {
1151 	struct client *c = client_connect();
1152 	struct wl_registry *registry;
1153 
1154 	registry = wl_display_get_registry(c->wl_display);
1155 	wl_registry_add_listener(registry, &zombie_fd_registry_listener, NULL);
1156 
1157 	/* Gets the registry */
1158 	wl_display_roundtrip(c->wl_display);
1159 
1160 	/* push out the fd_passer bind */
1161 	wl_display_roundtrip(c->wl_display);
1162 
1163 	/* push out our fd_passer.destroy */
1164 	wl_display_roundtrip(c->wl_display);
1165 
1166 	wl_registry_destroy(registry);
1167 
1168 	client_disconnect_nocheck(c);
1169 }
1170 
1171 struct passer_data {
1172 	struct wl_resource *conjoined_passer;
1173 };
1174 
1175 static void
feed_pipe(int fd,char tosend)1176 feed_pipe(int fd, char tosend)
1177 {
1178 	int count;
1179 
1180 	do {
1181 		count = write(fd, &tosend, 1);
1182 	} while (count != 1 && errno == EAGAIN);
1183 	assert(count == 1);
1184 	close(fd);
1185 }
1186 
1187 static void
fd_passer_clobber(struct wl_client * client,struct wl_resource * res)1188 fd_passer_clobber(struct wl_client *client, struct wl_resource *res)
1189 {
1190 	struct passer_data *pdata = wl_resource_get_user_data(res);
1191 	int pipes1[2], pipes2[2], ret;
1192 
1193 	if (pdata->conjoined_passer) {
1194 		ret = pipe(pipes1);
1195 		assert(ret == 0);
1196 		ret = pipe(pipes2);
1197 		assert(ret == 0);
1198 
1199 		wl_resource_queue_event(res, FD_PASSER_FD, pipes1[0]);
1200 		fd_passer_send_fd(pdata->conjoined_passer, pipes2[0]);
1201 		feed_pipe(pipes1[1], '1');
1202 		feed_pipe(pipes2[1], '2');
1203 		close(pipes1[0]);
1204 		close(pipes2[0]);
1205 	}
1206 	wl_resource_destroy(res);
1207 }
1208 
1209 static void
fd_passer_twin(struct wl_client * client,struct wl_resource * res,struct wl_resource * passer)1210 fd_passer_twin(struct wl_client *client, struct wl_resource *res, struct wl_resource *passer)
1211 {
1212 	struct passer_data *pdata = wl_resource_get_user_data(res);
1213 
1214 	pdata->conjoined_passer = passer;
1215 }
1216 
1217 static const struct fd_passer_interface fdp_interface = {
1218 	fd_passer_clobber,
1219 	fd_passer_twin
1220 };
1221 
1222 static void
pdata_destroy(struct wl_resource * res)1223 pdata_destroy(struct wl_resource *res)
1224 {
1225 	struct passer_data *pdata = wl_resource_get_user_data(res);
1226 
1227 	free(pdata);
1228 }
1229 
1230 static void
bind_fd_passer(struct wl_client * client,void * data,uint32_t vers,uint32_t id)1231 bind_fd_passer(struct wl_client *client, void *data,
1232 	       uint32_t vers, uint32_t id)
1233 {
1234 	struct wl_resource *res;
1235 	struct passer_data *pdata;
1236 
1237 	pdata = malloc(sizeof(*pdata));
1238 	assert(pdata);
1239 	pdata->conjoined_passer = NULL;
1240 
1241 	res = wl_resource_create(client, &fd_passer_interface, vers, id);
1242 	wl_resource_set_implementation(res, &fdp_interface, pdata, pdata_destroy);
1243 	assert(res);
1244 	if (vers == 1) {
1245 		fd_passer_send_pre_fd(res);
1246 		fd_passer_send_fd(res, fileno(stdin));
1247 	}
1248 }
1249 
TEST(zombie_fd)1250 TEST(zombie_fd)
1251 {
1252 	struct display *d;
1253 	struct wl_global *g;
1254 
1255 	d = display_create();
1256 
1257 	g = wl_global_create(d->wl_display, &fd_passer_interface,
1258 			     1, d, bind_fd_passer);
1259 
1260 	client_create_noarg(d, zombie_client);
1261 	display_run(d);
1262 
1263 	wl_global_destroy(g);
1264 
1265 	display_destroy(d);
1266 }
1267 
1268 
1269 static void
double_pre_fd(void * data,struct fd_passer * fdp)1270 double_pre_fd(void *data, struct fd_passer *fdp)
1271 {
1272 	assert(false);
1273 }
1274 
1275 static void
double_fd(void * data,struct fd_passer * fdp,int32_t fd)1276 double_fd(void *data, struct fd_passer *fdp, int32_t fd)
1277 {
1278 	char buf;
1279 	int count;
1280 
1281 	do {
1282 		count = read(fd, &buf, 1);
1283 	} while (count != 1 && errno == EAGAIN);
1284 	assert(count == 1);
1285 
1286 	close(fd);
1287 	fd_passer_destroy(fdp);
1288 	assert(buf == '2');
1289 }
1290 
1291 struct fd_passer_listener double_fd_passer_listener = {
1292 	double_pre_fd,
1293 	double_fd,
1294 };
1295 
1296 
1297 static void
double_zombie_fd_handle_globals(void * data,struct wl_registry * registry,uint32_t id,const char * intf,uint32_t ver)1298 double_zombie_fd_handle_globals(void *data, struct wl_registry *registry,
1299 			 uint32_t id, const char *intf, uint32_t ver)
1300 {
1301 	struct fd_passer *fdp1, *fdp2;
1302 
1303 	if (!strcmp(intf, "fd_passer")) {
1304 		fdp1 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
1305 		fd_passer_add_listener(fdp1, &double_fd_passer_listener, NULL);
1306 		fdp2 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
1307 		fd_passer_add_listener(fdp2, &double_fd_passer_listener, NULL);
1308 		fd_passer_conjoin(fdp1, fdp2);
1309 		fd_passer_destroy(fdp1);
1310 	}
1311 }
1312 
1313 static const struct wl_registry_listener double_zombie_fd_registry_listener = {
1314 	double_zombie_fd_handle_globals,
1315 	NULL
1316 };
1317 
1318 static void
double_zombie_client(void * data)1319 double_zombie_client(void *data)
1320 {
1321 	struct client *c = client_connect();
1322 	struct wl_registry *registry;
1323 
1324 	registry = wl_display_get_registry(c->wl_display);
1325 	wl_registry_add_listener(registry, &double_zombie_fd_registry_listener, NULL);
1326 
1327 	/* Gets the registry */
1328 	wl_display_roundtrip(c->wl_display);
1329 
1330 	/* One more so server can respond to conjoin+destroy */
1331 	wl_display_roundtrip(c->wl_display);
1332 
1333 	/* And finally push out our last fd_passer.destroy */
1334 	wl_display_roundtrip(c->wl_display);
1335 
1336 	wl_registry_destroy(registry);
1337 
1338 	client_disconnect_nocheck(c);
1339 }
1340 
TEST(zombie_fd_errant_consumption)1341 TEST(zombie_fd_errant_consumption)
1342 {
1343 	struct display *d;
1344 	struct wl_global *g;
1345 
1346 	d = display_create();
1347 
1348 	g = wl_global_create(d->wl_display, &fd_passer_interface,
1349 			     2, d, bind_fd_passer);
1350 
1351 	client_create_noarg(d, double_zombie_client);
1352 	display_run(d);
1353 
1354 	wl_global_destroy(g);
1355 
1356 	display_destroy(d);
1357 }
1358