From 2f07ef6963a81cffabdac33c19c413db5bebc499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Sat, 16 Feb 2013 14:29:24 -0500 Subject: [PATCH] xkb: Don't call exit on failure in weston_compositor_xkb_init() This will exit without cleaning vt modes and leave the system stuck. https://bugs.freedesktop.org/show_bug.cgi?id=60817 --- src/compositor-drm.c | 51 ++++++++++++++++++++++++++++++-------------- src/compositor-x11.c | 3 ++- src/compositor.c | 50 ++++++++++++++++++++++++++----------------- src/compositor.h | 2 +- src/evdev.c | 20 ++++++++++++++--- src/evdev.h | 2 ++ 6 files changed, 87 insertions(+), 41 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 37e82531..57fcf135 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -1934,7 +1934,7 @@ drm_restore(struct weston_compositor *ec) static const char default_seat[] = "seat0"; -static void +static int device_added(struct udev_device *udev_device, struct drm_seat *master) { struct weston_compositor *c; @@ -1949,7 +1949,7 @@ device_added(struct udev_device *udev_device, struct drm_seat *master) device_seat = default_seat; if (strcmp(device_seat, master->seat_id)) - return; + return 0; c = master->base.compositor; devnode = udev_device_get_devnode(udev_device); @@ -1960,14 +1960,18 @@ device_added(struct udev_device *udev_device, struct drm_seat *master) fd = weston_launcher_open(c, devnode, O_RDWR | O_NONBLOCK); if (fd < 0) { weston_log("opening input device '%s' failed.\n", devnode); - return; + return -1; } device = evdev_device_create(&master->base, devnode, fd); - if (!device) { + if (device == EVDEV_UNHANDLED_DEVICE) { close(fd); weston_log("not using input device '%s'.\n", devnode); - return; + return 0; + } else if (device == NULL) { + close(fd); + weston_log("failed to create input device '%s'.\n", devnode); + return -1; } calibration_values = @@ -1993,9 +1997,11 @@ device_added(struct udev_device *udev_device, struct drm_seat *master) } wl_list_insert(master->devices_list.prev, &device->link); + + return 0; } -static void +static int evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) { struct drm_seat *seat = (struct drm_seat *) seat_base; @@ -2017,7 +2023,11 @@ evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) continue; } - device_added(device, seat); + if (device_added(device, seat) < 0) { + udev_device_unref(device); + udev_enumerate_unref(e); + return -1; + } udev_device_unref(device); } @@ -2034,6 +2044,8 @@ evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) "(Weston backend option 'seat', " "udev device property ID_SEAT)\n"); } + + return 0; } static int @@ -2136,7 +2148,7 @@ drm_led_update(struct weston_seat *seat_base, enum weston_led leds) evdev_led_update(device, leds); } -static void +static struct drm_seat * evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat_id) { @@ -2144,7 +2156,7 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, seat = malloc(sizeof *seat); if (seat == NULL) - return; + return NULL; memset(seat, 0, sizeof *seat); weston_seat_init(&seat->base, c); @@ -2152,13 +2164,17 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, wl_list_init(&seat->devices_list); seat->seat_id = strdup(seat_id); - if (!evdev_enable_udev_monitor(udev, &seat->base)) { - free(seat->seat_id); - free(seat); - return; - } + if (!evdev_enable_udev_monitor(udev, &seat->base)) + goto err; + if (evdev_add_devices(udev, &seat->base) < 0) + goto err; - evdev_add_devices(udev, &seat->base); + return seat; + + err: + free(seat->seat_id); + free(seat); + return NULL; } static void @@ -2486,7 +2502,10 @@ drm_compositor_create(struct wl_display *display, path = NULL; - evdev_input_create(&ec->base, ec->udev, seat); + if (evdev_input_create(&ec->base, ec->udev, seat) == NULL) { + weston_log("failed to create input devices\n"); + goto err_sprite; + } loop = wl_display_get_event_loop(ec->base.wl_display); ec->drm_source = diff --git a/src/compositor-x11.c b/src/compositor-x11.c index e39c4820..7a9998cb 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -303,7 +303,8 @@ x11_input_create(struct x11_compositor *c, int no_input) weston_seat_init_pointer(&c->core_seat); keymap = x11_compositor_get_keymap(c); - weston_seat_init_keyboard(&c->core_seat, keymap); + if (weston_seat_init_keyboard(&c->core_seat, keymap) < 0) + return -1; if (keymap) xkb_map_unref(keymap); diff --git a/src/compositor.c b/src/compositor.c index 3b16220c..6ee3a79f 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -2363,14 +2363,15 @@ device_handle_new_drag_icon(struct wl_listener *listener, void *data) weston_seat_update_drag_surface(seat, 0, 0); } -static void weston_compositor_xkb_init(struct weston_compositor *ec, - struct xkb_rule_names *names) +static int +weston_compositor_xkb_init(struct weston_compositor *ec, + struct xkb_rule_names *names) { if (ec->xkb_context == NULL) { ec->xkb_context = xkb_context_new(0); if (ec->xkb_context == NULL) { weston_log("failed to create XKB context\n"); - exit(1); + return -1; } } @@ -2382,6 +2383,8 @@ static void weston_compositor_xkb_init(struct weston_compositor *ec, ec->xkb_names.model = strdup("pc105"); if (!ec->xkb_names.layout) ec->xkb_names.layout = strdup("us"); + + return 0; } static void xkb_info_destroy(struct weston_xkb_info *xkb_info) @@ -2407,7 +2410,7 @@ static void weston_compositor_xkb_destroy(struct weston_compositor *ec) xkb_context_unref(ec->xkb_context); } -static void +static int weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info) { char *keymap_str; @@ -2436,7 +2439,7 @@ weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info) keymap_str = xkb_map_get_as_string(xkb_info->keymap); if (keymap_str == NULL) { weston_log("failed to get string version of keymap\n"); - exit(EXIT_FAILURE); + return -1; } xkb_info->keymap_size = strlen(keymap_str) + 1; @@ -2458,21 +2461,21 @@ weston_xkb_info_new_keymap(struct weston_xkb_info *xkb_info) strcpy(xkb_info->keymap_area, keymap_str); free(keymap_str); - return; + return 0; err_dev_zero: close(xkb_info->keymap_fd); xkb_info->keymap_fd = -1; err_keymap_str: free(keymap_str); - exit(EXIT_FAILURE); + return -1; } -static void +static int weston_compositor_build_global_keymap(struct weston_compositor *ec) { if (ec->xkb_info.keymap != NULL) - return; + return 0; ec->xkb_info.keymap = xkb_map_new_from_names(ec->xkb_context, &ec->xkb_names, @@ -2480,28 +2483,32 @@ weston_compositor_build_global_keymap(struct weston_compositor *ec) if (ec->xkb_info.keymap == NULL) { weston_log("failed to compile global XKB keymap\n"); weston_log(" tried rules %s, model %s, layout %s, variant %s, " - "options %s", + "options %s\n", ec->xkb_names.rules, ec->xkb_names.model, ec->xkb_names.layout, ec->xkb_names.variant, ec->xkb_names.options); - exit(1); + return -1; } - weston_xkb_info_new_keymap(&ec->xkb_info); + if (weston_xkb_info_new_keymap(&ec->xkb_info) < 0) + return -1; + + return 0; } -WL_EXPORT void +WL_EXPORT int weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) { if (seat->has_keyboard) - return; + return 0; if (keymap != NULL) { seat->xkb_info.keymap = xkb_map_ref(keymap); - weston_xkb_info_new_keymap(&seat->xkb_info); - } - else { - weston_compositor_build_global_keymap(seat->compositor); + if (weston_xkb_info_new_keymap(&seat->xkb_info) < 0) + return -1; + } else { + if (weston_compositor_build_global_keymap(seat->compositor) < 0) + return -1; seat->xkb_info = seat->compositor->xkb_info; seat->xkb_info.keymap = xkb_map_ref(seat->xkb_info.keymap); } @@ -2509,7 +2516,7 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) seat->xkb_state.state = xkb_state_new(seat->xkb_info.keymap); if (seat->xkb_state.state == NULL) { weston_log("failed to initialise XKB state\n"); - exit(1); + return -1; } seat->xkb_state.leds = 0; @@ -2518,6 +2525,8 @@ weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) wl_seat_set_keyboard(&seat->seat, &seat->keyboard.keyboard); seat->has_keyboard = 1; + + return 0; } WL_EXPORT void @@ -2991,7 +3000,8 @@ weston_compositor_init(struct weston_compositor *ec, weston_plane_init(&ec->primary_plane, 0, 0); - weston_compositor_xkb_init(ec, &xkb_names); + if (weston_compositor_xkb_init(ec, &xkb_names) < 0) + return -1; ec->ping_handler = NULL; diff --git a/src/compositor.h b/src/compositor.h index c39abe38..fdde7626 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -738,7 +738,7 @@ void weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec); void weston_seat_init_pointer(struct weston_seat *seat); -void +int weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap); void weston_seat_init_touch(struct weston_seat *seat); diff --git a/src/evdev.c b/src/evdev.c index 0b99c436..286543a0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -397,7 +397,7 @@ evdev_device_data(int fd, uint32_t mask, void *data) } static int -evdev_configure_device(struct evdev_device *device) +evdev_handle_device(struct evdev_device *device) { struct input_absinfo absinfo; unsigned long ev_bits[NBITS(EV_MAX)]; @@ -483,9 +483,15 @@ evdev_configure_device(struct evdev_device *device) weston_log("input device %s, %s " "ignored: unsupported device type\n", device->devname, device->devnode); - return -1; + return 0; } + return 1; +} + +static int +evdev_configure_device(struct evdev_device *device) +{ if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) { weston_seat_init_pointer(device->seat); @@ -496,7 +502,8 @@ evdev_configure_device(struct evdev_device *device) device->caps & EVDEV_BUTTON ? " button" : ""); } if ((device->caps & EVDEV_KEYBOARD)) { - weston_seat_init_keyboard(device->seat, NULL); + if (weston_seat_init_keyboard(device->seat, NULL) < 0) + return -1; weston_log("input device %s, %s is a keyboard\n", device->devname, device->devnode); } @@ -538,6 +545,13 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); device->devname = strdup(devname); + if (!evdev_handle_device(device)) { + free(device->devnode); + free(device->devname); + free(device); + return EVDEV_UNHANDLED_DEVICE; + } + if (evdev_configure_device(device) == -1) goto err1; diff --git a/src/evdev.h b/src/evdev.h index a90f90cd..ccbb2224 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -88,6 +88,8 @@ struct evdev_device { #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1) /* end copied */ +#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1) + struct evdev_dispatch; struct evdev_dispatch_interface {