launcher: Handle drm set/drop master and vt switch signals in launcher
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 18 Sep 2013 05:15:37 +0000 (22:15 -0700)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 18 Sep 2013 18:14:14 +0000 (11:14 -0700)
src/compositor-drm.c
src/launcher-util.c
src/launcher-util.h
src/tty.c
src/weston-launch.c
src/weston-launch.h

index 83ff1c8..4ee068b 100644 (file)
@@ -2242,7 +2242,7 @@ drm_restore(struct weston_compositor *ec)
 {
        struct drm_compositor *d = (struct drm_compositor *) ec;
 
-       if (weston_launcher_drm_set_master(d->base.launcher, d->drm.fd, 0) < 0)
+       if (ec->launcher == NULL && drmDropMaster(d->drm.fd) < 0)
                weston_log("failed to drop master: %m\n");
        tty_reset(d->tty);
 }
@@ -2266,7 +2266,7 @@ drm_destroy(struct weston_compositor *ec)
        if (d->gbm)
                gbm_device_destroy(d->gbm);
 
-       if (weston_launcher_drm_set_master(d->base.launcher, d->drm.fd, 0) < 0)
+       if (d->base.launcher == NULL && drmDropMaster(d->drm.fd) < 0)
                weston_log("failed to drop master: %m\n");
        tty_destroy(d->tty);
 
@@ -2318,8 +2318,7 @@ session_notify(struct wl_listener *listener, void *data)
        if (ec->base.session_active) {
                weston_log("activating session\n");
                compositor->focus = 1;
-               if (weston_launcher_drm_set_master(ec->base.launcher,
-                                                  ec->drm.fd, 1)) {
+               if (ec->base.launcher == NULL && drmSetMaster(ec->drm.fd)) {
                        weston_log("failed to set master: %m\n");
                        wl_display_terminate(compositor->wl_display);
                }
@@ -2357,8 +2356,7 @@ session_notify(struct wl_listener *listener, void *data)
                                        output->crtc_id, 0, 0,
                                        0, 0, 0, 0, 0, 0, 0, 0);
 
-               if (weston_launcher_drm_set_master(ec->base.launcher,
-                                                  ec->drm.fd, 0) < 0)
+               if (ec->base.launcher == NULL && drmDropMaster(ec->drm.fd) < 0)
                        weston_log("failed to drop master: %m\n");
        };
 }
@@ -2692,8 +2690,7 @@ err_sprite:
 err_udev_dev:
        udev_device_unref(drm_device);
 err_tty:
-       if (weston_launcher_drm_set_master(ec->base.launcher,
-                                          ec->drm.fd, 0) < 0)
+       if (ec->base.launcher == NULL && drmDropMaster(ec->drm.fd) < 0)
                weston_log("failed to drop master: %m\n");
        tty_destroy(ec->tty);
 err_udev:
index 8c3b496..75e7051 100644 (file)
@@ -46,6 +46,7 @@ union cmsg_data { unsigned char b[4]; int fd; };
 struct weston_launcher {
        struct weston_compositor *compositor;
        int fd;
+       struct wl_event_source *source;
 };
 
 int
@@ -111,65 +112,45 @@ weston_launcher_open(struct weston_launcher *launcher,
        return data->fd;
 }
 
-int
-weston_launcher_drm_set_master(struct weston_launcher *launcher,
-                              int drm_fd, char master)
+static int
+weston_launcher_data(int fd, uint32_t mask, void *data)
 {
-       struct msghdr msg;
-       struct cmsghdr *cmsg;
-       struct iovec iov;
-       char control[CMSG_SPACE(sizeof(drm_fd))];
-       int ret;
-       ssize_t len;
-       struct weston_launcher_set_master message;
-       union cmsg_data *data;
+       struct weston_launcher *launcher = data;
+       int len, ret;
 
-       if (launcher == NULL) {
-               if (master)
-                       return drmSetMaster(drm_fd);
-               else
-                       return drmDropMaster(drm_fd);
+       if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
+               weston_log("launcher socket closed, exiting\n");
+               exit(-1);
        }
 
-       memset(&msg, 0, sizeof msg);
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       msg.msg_control = control;
-       msg.msg_controllen = sizeof control;
-       cmsg = CMSG_FIRSTHDR(&msg);
-       cmsg->cmsg_level = SOL_SOCKET;
-       cmsg->cmsg_type = SCM_RIGHTS;
-       cmsg->cmsg_len = CMSG_LEN(sizeof(drm_fd));
-
-       data = (union cmsg_data *) CMSG_DATA(cmsg);
-       data->fd = drm_fd;
-       msg.msg_controllen = cmsg->cmsg_len;
-
-       iov.iov_base = &message;
-       iov.iov_len = sizeof message;
-
-       message.header.opcode = WESTON_LAUNCHER_DRM_SET_MASTER;
-       message.set_master = master;
-
-       do {
-               len = sendmsg(launcher->fd, &msg, 0);
-       } while (len < 0 && errno == EINTR);
-       if (len < 0)
-               return -1;
-
        do {
                len = recv(launcher->fd, &ret, sizeof ret, 0);
        } while (len < 0 && errno == EINTR);
-       if (len < 0)
-               return -1;
 
-       return ret;
+       switch (ret) {
+       case WESTON_LAUNCHER_ACTIVATE:
+               launcher->compositor->session_active = 1;
+               wl_signal_emit(&launcher->compositor->session_signal,
+                              launcher->compositor);
+               break;
+       case WESTON_LAUNCHER_DEACTIVATE:
+               launcher->compositor->session_active = 0;
+               wl_signal_emit(&launcher->compositor->session_signal,
+                              launcher->compositor);
+               break;
+       default:
+               weston_log("unexpected event from weston-launch\n");
+               break;
+       }
+
+       return 1;
 }
 
 struct weston_launcher *
 weston_launcher_connect(struct weston_compositor *compositor)
 {
        struct weston_launcher *launcher;
+       struct wl_event_loop *loop;
        int fd;
 
        fd = weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
@@ -183,6 +164,16 @@ weston_launcher_connect(struct weston_compositor *compositor)
        launcher->compositor = compositor;
        launcher->fd = fd;
 
+       loop = wl_display_get_event_loop(compositor->wl_display);
+       launcher->source = wl_event_loop_add_fd(loop, launcher->fd,
+                                               WL_EVENT_READABLE,
+                                               weston_launcher_data,
+                                               launcher);
+       if (launcher->source == NULL) {
+               free(launcher);
+               return NULL;
+       }
+
        return launcher;
 }
 
index a3a7041..5fa9248 100644 (file)
@@ -38,8 +38,5 @@ weston_launcher_destroy(struct weston_launcher *launcher);
 int
 weston_launcher_open(struct weston_launcher *launcher,
                     const char *path, int flags);
-int
-weston_launcher_drm_set_master(struct weston_launcher *launcher,
-                              int drm_fd, char master);
 
 #endif
index f05f55b..2ac7236 100644 (file)
--- a/src/tty.c
+++ b/src/tty.c
@@ -219,18 +219,20 @@ tty_create(struct weston_compositor *compositor, int tty_nr)
                goto err_kdkbmode;
        }
 
-       mode.mode = VT_PROCESS;
-       mode.relsig = SIGUSR1;
-       mode.acqsig = SIGUSR1;
-       if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) {
-               weston_log("failed to take control of vt handling\n");
-               goto err_kdmode;
-       }
+       if (compositor->launcher == NULL) {
+               mode.mode = VT_PROCESS;
+               mode.relsig = SIGUSR1;
+               mode.acqsig = SIGUSR1;
+               if (ioctl(tty->fd, VT_SETMODE, &mode) < 0) {
+                       weston_log("failed to take control of vt handling\n");
+                       goto err_kdmode;
+               }
 
-       tty->vt_source =
-               wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty);
-       if (!tty->vt_source)
-               goto err_vtmode;
+               tty->vt_source =
+                       wl_event_loop_add_signal(loop, SIGUSR1, vt_handler, tty);
+               if (!tty->vt_source)
+                       goto err_vtmode;
+       }
 
        return tty;
 
@@ -283,7 +285,8 @@ tty_destroy(struct tty *tty)
        if (tty->input_source)
                wl_event_source_remove(tty->input_source);
 
-       wl_event_source_remove(tty->vt_source);
+       if (tty->vt_source)
+               wl_event_source_remove(tty->vt_source);
 
        tty_reset(tty);
 
index 80c06a8..87f4641 100644 (file)
@@ -68,6 +68,7 @@ struct weston_launch {
        int tty;
        int ttynr;
        int sock[2];
+       int drm_fd;
        struct passwd *pw;
 
        int signalfd;
@@ -223,6 +224,8 @@ setup_signals(struct weston_launch *wl)
        sigaddset(&mask, SIGCHLD);
        sigaddset(&mask, SIGINT);
        sigaddset(&mask, SIGTERM);
+       sigaddset(&mask, SIGUSR1);
+       sigaddset(&mask, SIGUSR2);
        ret = sigprocmask(SIG_BLOCK, &mask, NULL);
        assert(ret == 0);
 
@@ -243,48 +246,15 @@ setenv_fd(const char *env, int fd)
 }
 
 static int
-handle_setmaster(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
+send_reply(struct weston_launch *wl, int reply)
 {
-       int ret = -1;
-       struct cmsghdr *cmsg;
-       struct weston_launcher_set_master *message;
-       union cmsg_data *data;
-
-       if (len != sizeof(*message)) {
-               error(0, 0, "missing value in setmaster request");
-               goto out;
-       }
-
-       message = msg->msg_iov->iov_base;
-
-       cmsg = CMSG_FIRSTHDR(msg);
-       if (!cmsg ||
-           cmsg->cmsg_level != SOL_SOCKET ||
-           cmsg->cmsg_type != SCM_RIGHTS) {
-               error(0, 0, "invalid control message");
-               goto out;
-       }
-
-       data = (union cmsg_data *) CMSG_DATA(cmsg);
-       if (data->fd == -1) {
-               error(0, 0, "missing drm fd in socket request");
-               goto out;
-       }
+       int len;
 
-       if (message->set_master)
-               ret = drmSetMaster(data->fd);
-       else
-               ret = drmDropMaster(data->fd);
-
-       close(data->fd);
-out:
        do {
-               len = send(wl->sock[0], &ret, sizeof ret, 0);
+               len = send(wl->sock[0], &reply, sizeof reply, 0);
        } while (len < 0 && errno == EINTR);
-       if (len < 0)
-               return -1;
 
-       return 0;
+       return len;
 }
 
 static int
@@ -354,6 +324,9 @@ err0:
        if (len < 0)
                return -1;
 
+       if (major(s.st_rdev) == DRM_MAJOR)
+               wl->drm_fd = fd;
+
        return 0;
 }
 
@@ -388,9 +361,6 @@ handle_socket_msg(struct weston_launch *wl)
        case WESTON_LAUNCHER_OPEN:
                ret = handle_open(wl, &msg, len);
                break;
-       case WESTON_LAUNCHER_DRM_SET_MASTER:
-               ret = handle_setmaster(wl, &msg, len);
-               break;
        }
 
        return ret;
@@ -451,6 +421,16 @@ handle_signal(struct weston_launch *wl)
                if (wl->child)
                        kill(wl->child, sig.ssi_signo);
                break;
+       case SIGUSR1:
+               send_reply(wl, WESTON_LAUNCHER_DEACTIVATE);
+               drmDropMaster(wl->drm_fd);
+               ioctl(wl->tty, VT_RELDISP, 1);
+               break;
+       case SIGUSR2:
+               ioctl(wl->tty, VT_RELDISP, VT_ACKACQ);
+               drmSetMaster(wl->drm_fd);
+               send_reply(wl, WESTON_LAUNCHER_ACTIVATE);
+               break;
        default:
                return -1;
        }
@@ -462,6 +442,7 @@ static int
 setup_tty(struct weston_launch *wl, const char *tty)
 {
        struct stat buf;
+       struct vt_mode mode = { 0 };
        char *t;
 
        if (!wl->new_user) {
@@ -500,6 +481,12 @@ setup_tty(struct weston_launch *wl, const char *tty)
                wl->ttynr = minor(buf.st_rdev);
        }
 
+       mode.mode = VT_PROCESS;
+       mode.relsig = SIGUSR1;
+       mode.acqsig = SIGUSR2;
+       if (ioctl(wl->tty, VT_SETMODE, &mode) < 0)
+               error(1, errno, "failed to take control of vt handling\n");
+
        return 0;
 }
 
index 5be013e..e20c4c7 100644 (file)
 
 enum weston_launcher_opcode {
        WESTON_LAUNCHER_OPEN,
-       WESTON_LAUNCHER_DRM_SET_MASTER
+};
+
+enum weston_launcher_event {
+       WESTON_LAUNCHER_SUCCESS,
+       WESTON_LAUNCHER_ACTIVATE,
+       WESTON_LAUNCHER_DEACTIVATE
 };
 
 struct weston_launcher_message {
@@ -38,9 +43,4 @@ struct weston_launcher_open {
        char path[0];
 };
 
-struct weston_launcher_set_master {
-       struct weston_launcher_message header;
-       int set_master;
-};
-
 #endif