weston-launch: Revoke and close input fds when we vt switch away
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 25 Oct 2013 20:34:58 +0000 (13:34 -0700)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 25 Oct 2013 20:34:58 +0000 (13:34 -0700)
We used to leak the input fds, as weston would reopen all fds on vt
enter.  We could just close them after sending the open fd through the
socket, but this patch also adds support for the new EVIOCREVOKE evdev
ioctl, that revokes the fd in question (including the copy that we
sent to the compositor).

https://bugs.freedesktop.org/show_bug.cgi?id=70849

src/weston-launch.c

index 8118d03..03a6a43 100644 (file)
 #define KDSKBMUTE      0x4B51
 #endif
 
+#ifndef EVIOCREVOKE
+#define EVIOCREVOKE _IOW('E', 0x91, int)
+#endif
+
 #define MAX_ARGV_SIZE 256
 
 struct weston_launch {
@@ -73,6 +77,7 @@ struct weston_launch {
        int ttynr;
        int sock[2];
        int drm_fd;
+       int last_input_fd;
        int kb_mode;
        struct passwd *pw;
 
@@ -335,6 +340,9 @@ err0:
 
        if (fd != -1 && major(s.st_rdev) == DRM_MAJOR)
                wl->drm_fd = fd;
+       if (fd != -1 && major(s.st_rdev) == INPUT_MAJOR &&
+           wl->last_input_fd < fd)
+               wl->last_input_fd = fd;
 
        return 0;
 }
@@ -406,6 +414,22 @@ quit(struct weston_launch *wl, int status)
        exit(status);
 }
 
+static void
+close_input_fds(struct weston_launch *wl)
+{
+       struct stat s;
+       int fd;
+
+       for (fd = 3; fd <= wl->last_input_fd; fd++) {
+               if (fstat(fd, &s) == 0 && major(s.st_rdev) == INPUT_MAJOR) {
+                       /* EVIOCREVOKE may fail if the kernel doesn't
+                        * support it, but all we can do is ignore it. */
+                       ioctl(fd, EVIOCREVOKE, 0);
+                       close(fd);
+               }
+       }
+}
+
 static int
 handle_signal(struct weston_launch *wl)
 {
@@ -444,6 +468,7 @@ handle_signal(struct weston_launch *wl)
                break;
        case SIGUSR1:
                send_reply(wl, WESTON_LAUNCHER_DEACTIVATE);
+               close_input_fds(wl);
                drmDropMaster(wl->drm_fd);
                ioctl(wl->tty, VT_RELDISP, 1);
                break;