tests: Add a test for fd leaks on zombie objects
Until recently, if a client destroying a resource raced with the
server generating an event on that resource that delivered a file
descriptor, we would leak the fd.
This tests for a leaked fd from that race condition.
Reviewed-by: Daniel Stone <daniels@collabora.com>
Signed-off-by: Derek Foreman <derekf@osg.samsung.com>
Derek Foreman authored 6 years ago
Daniel Stone committed 6 years ago
113 | 113 | BUILT_SOURCES = \ |
114 | 114 | $(nodist_libwayland_server_la_SOURCES) \ |
115 | 115 | $(nodist_libwayland_client_la_SOURCES) \ |
116 | $(nodist_headers_test_SOURCES) | |
116 | $(nodist_headers_test_SOURCES) \ | |
117 | $(nodist_display_test_SOURCES) | |
117 | 118 | |
118 | 119 | CLEANFILES = $(BUILT_SOURCES) doc/doxygen/doxygen_sqlite3.db |
119 | 120 | DISTCLEANFILES = src/wayland-version.h |
205 | 206 | client_test_LDADD = libtest-runner.la |
206 | 207 | display_test_SOURCES = tests/display-test.c |
207 | 208 | display_test_LDADD = libtest-runner.la |
209 | nodist_display_test_SOURCES = \ | |
210 | protocol/tests-server-protocol.h \ | |
211 | protocol/tests-client-protocol.h \ | |
212 | protocol/tests-protocol.c | |
208 | 213 | connection_test_SOURCES = tests/connection-test.c |
209 | 214 | connection_test_LDADD = libtest-runner.la |
210 | 215 | event_loop_test_SOURCES = tests/event-loop-test.c |
0 | <?xml version="1.0" encoding="UTF-8"?> | |
1 | <protocol name="build_time_wayland_tests"> | |
2 | ||
3 | <copyright> | |
4 | Copyright © 2017 Samsung Electronics Co., Ltd | |
5 | ||
6 | Permission is hereby granted, free of charge, to any person | |
7 | obtaining a copy of this software and associated documentation files | |
8 | (the "Software"), to deal in the Software without restriction, | |
9 | including without limitation the rights to use, copy, modify, merge, | |
10 | publish, distribute, sublicense, and/or sell copies of the Software, | |
11 | and to permit persons to whom the Software is furnished to do so, | |
12 | subject to the following conditions: | |
13 | ||
14 | The above copyright notice and this permission notice (including the | |
15 | next paragraph) shall be included in all copies or substantial | |
16 | portions of the Software. | |
17 | ||
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | SOFTWARE. | |
26 | </copyright> | |
27 | ||
28 | <interface name="fd_passer" version="1"> | |
29 | <description summary="Sends an event with an fd"> | |
30 | A trivial interface for fd passing tests. | |
31 | </description> | |
32 | ||
33 | <request name="destroy" type="destructor"/> | |
34 | ||
35 | <event name="pre_fd"/> | |
36 | ||
37 | <event name="fd"> | |
38 | <description summary="passes a file descriptor"/> | |
39 | <arg name="fd" type="fd" summary="file descriptor"/> | |
40 | </event> | |
41 | </interface> | |
42 | </protocol> |
46 | 46 | #include "test-runner.h" |
47 | 47 | #include "test-compositor.h" |
48 | 48 | |
49 | #include "tests-server-protocol.h" | |
50 | #include "tests-client-protocol.h" | |
51 | ||
49 | 52 | struct display_destroy_listener { |
50 | 53 | struct wl_listener listener; |
51 | 54 | int done; |
1065 | 1068 | |
1066 | 1069 | display_destroy(d); |
1067 | 1070 | } |
1071 | ||
1072 | static void | |
1073 | pre_fd(void *data, struct fd_passer *fdp) | |
1074 | { | |
1075 | fd_passer_destroy(fdp); | |
1076 | } | |
1077 | ||
1078 | static void | |
1079 | fd(void *data, struct fd_passer *fdp, int32_t fd) | |
1080 | { | |
1081 | /* We destroyed the resource before this event */ | |
1082 | assert(false); | |
1083 | } | |
1084 | ||
1085 | struct fd_passer_listener fd_passer_listener = { | |
1086 | pre_fd, | |
1087 | fd, | |
1088 | }; | |
1089 | ||
1090 | static void | |
1091 | zombie_fd_handle_globals(void *data, struct wl_registry *registry, | |
1092 | uint32_t id, const char *intf, uint32_t ver) | |
1093 | { | |
1094 | struct fd_passer *fdp; | |
1095 | ||
1096 | if (!strcmp(intf, "fd_passer")) { | |
1097 | fdp = wl_registry_bind(registry, id, &fd_passer_interface, 1); | |
1098 | fd_passer_add_listener(fdp, &fd_passer_listener, NULL); | |
1099 | } | |
1100 | } | |
1101 | ||
1102 | static const struct wl_registry_listener zombie_fd_registry_listener = { | |
1103 | zombie_fd_handle_globals, | |
1104 | NULL | |
1105 | }; | |
1106 | ||
1107 | static void | |
1108 | zombie_client(void *data) | |
1109 | { | |
1110 | struct client *c = client_connect(); | |
1111 | struct wl_registry *registry; | |
1112 | ||
1113 | registry = wl_display_get_registry(c->wl_display); | |
1114 | wl_registry_add_listener(registry, &zombie_fd_registry_listener, NULL); | |
1115 | ||
1116 | /* Gets the registry */ | |
1117 | wl_display_roundtrip(c->wl_display); | |
1118 | ||
1119 | /* push out the fd_passer bind */ | |
1120 | wl_display_roundtrip(c->wl_display); | |
1121 | ||
1122 | /* push out our fd_passer.destroy */ | |
1123 | wl_display_roundtrip(c->wl_display); | |
1124 | ||
1125 | wl_registry_destroy(registry); | |
1126 | ||
1127 | client_disconnect_nocheck(c); | |
1128 | } | |
1129 | ||
1130 | static void | |
1131 | fd_passer_clobber(struct wl_client *client, struct wl_resource *res) | |
1132 | { | |
1133 | wl_resource_destroy(res); | |
1134 | } | |
1135 | ||
1136 | static const struct fd_passer_interface fdp_interface = { | |
1137 | fd_passer_clobber, | |
1138 | }; | |
1139 | ||
1140 | static void | |
1141 | bind_fd_passer(struct wl_client *client, void *data, | |
1142 | uint32_t vers, uint32_t id) | |
1143 | { | |
1144 | struct wl_resource *res; | |
1145 | ||
1146 | res = wl_resource_create(client, &fd_passer_interface, vers, id); | |
1147 | wl_resource_set_implementation(res, &fdp_interface, NULL, NULL); | |
1148 | assert(res); | |
1149 | fd_passer_send_pre_fd(res); | |
1150 | fd_passer_send_fd(res, fileno(stdin)); | |
1151 | } | |
1152 | ||
1153 | TEST(zombie_fd) | |
1154 | { | |
1155 | struct display *d; | |
1156 | struct wl_global *g; | |
1157 | ||
1158 | d = display_create(); | |
1159 | ||
1160 | g = wl_global_create(d->wl_display, &fd_passer_interface, | |
1161 | 1, d, bind_fd_passer); | |
1162 | ||
1163 | client_create_noarg(d, zombie_client); | |
1164 | display_run(d); | |
1165 | ||
1166 | wl_global_destroy(g); | |
1167 | ||
1168 | display_destroy(d); | |
1169 | } |