Properly dispose event sources and event loops

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 91f4bcd..39b7a1b 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1424,15 +1424,19 @@
 	struct drm_compositor *d = (struct drm_compositor *) ec;
 	struct weston_input_device *input, *next;
 
+	wl_list_for_each_safe(input, next, &ec->input_device_list, link)
+		evdev_input_destroy(input);
+
+	wl_event_source_remove(d->udev_drm_source);
+	wl_event_source_remove(d->drm_source);
+
 	weston_compositor_shutdown(ec);
+
 	gbm_device_destroy(d->gbm);
 	destroy_sprites(d);
 	drmDropMaster(d->drm.fd);
 	tty_destroy(d->tty);
 
-	wl_list_for_each_safe(input, next, &ec->input_device_list, link)
-		evdev_input_destroy(input);
-
 	free(d);
 }
 
diff --git a/src/compositor.c b/src/compositor.c
index 47305cc..f9e1f23 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -2415,6 +2415,8 @@
 	struct weston_output *output, *next;
 
 	wl_event_source_remove(ec->idle_source);
+	if (ec->input_loop_source)
+		wl_event_source_remove(ec->input_loop_source);
 
 	if (ec->screenshooter)
 		screenshooter_destroy(ec->screenshooter);
@@ -2427,6 +2429,8 @@
 
 	wl_array_release(&ec->vertices);
 	wl_array_release(&ec->indices);
+
+	wl_event_loop_destroy(ec->input_loop);
 }
 
 static int on_term_signal(int signal_number, void *data)
diff --git a/src/evdev.c b/src/evdev.c
index 5dbe6ac..16f0e93 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -35,6 +35,7 @@
 	struct weston_input_device base;
 	struct wl_list devices_list;
 	struct udev_monitor *udev_monitor;
+	struct wl_event_source *udev_monitor_source;
 	char *seat_id;
 };
 
@@ -562,7 +563,7 @@
 	struct udev_enumerate *e;
 	struct udev_list_entry *entry;
 	struct udev_device *device;
-	const char *path;
+	const char *path, *sysname;
 
 	e = udev_enumerate_new(udev);
 	udev_enumerate_add_match_subsystem(e, "input");
@@ -571,8 +572,11 @@
 		path = udev_list_entry_get_name(entry);
 		device = udev_device_new_from_syspath(udev, path);
 
-		if (strncmp("event", udev_device_get_sysname(device), 5) != 0)
+		sysname = udev_device_get_sysname(device);
+		if (strncmp("event", sysname, 5) != 0) {
+			udev_device_unref(device);
 			continue;
+		}
 
 		device_added(device, input);
 
@@ -632,6 +636,7 @@
 {
 	struct wl_event_loop *loop;
 	struct weston_compositor *c = master->base.compositor;
+	int fd;
 
 	master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
 	if (!master->udev_monitor) {
@@ -644,12 +649,19 @@
 
 	if (udev_monitor_enable_receiving(master->udev_monitor)) {
 		fprintf(stderr, "udev: failed to bind the udev monitor\n");
+		udev_monitor_unref(master->udev_monitor);
 		return 0;
 	}
 
 	loop = wl_display_get_event_loop(c->wl_display);
-	wl_event_loop_add_fd(loop, udev_monitor_get_fd(master->udev_monitor),
-			     WL_EVENT_READABLE, evdev_udev_handler, master);
+	fd = udev_monitor_get_fd(master->udev_monitor);
+	master->udev_monitor_source =
+		wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
+				     evdev_udev_handler, master);
+	if (!master->udev_monitor_source) {
+		udev_monitor_unref(master->udev_monitor);
+		return 0;
+	}
 
 	return 1;
 }
@@ -696,6 +708,10 @@
 	struct evdev_input *input = (struct evdev_input *) input_base;
 
 	evdev_remove_devices(input_base);
+
+	udev_monitor_unref(input->udev_monitor);
+	wl_event_source_remove(input->udev_monitor_source);
+
 	wl_list_remove(&input->base.link);
 	free(input->seat_id);
 	free(input);
diff --git a/src/tty.c b/src/tty.c
index 249f5bb..c5e9e8a 100644
--- a/src/tty.c
+++ b/src/tty.c
@@ -221,6 +221,9 @@
 		ioctl(tty->fd, VT_WAITACTIVE, tty->starting_vt);
 	}
 
+	wl_event_source_remove(tty->input_source);
+	wl_event_source_remove(tty->vt_source);
+
 	close(tty->fd);
 
 	free(tty);