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, ®istry_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, ®istry_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