diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 83ff1c86f..4ee068bfc 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -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: diff --git a/src/launcher-util.c b/src/launcher-util.c index 8c3b496f9..75e7051f6 100644 --- a/src/launcher-util.c +++ b/src/launcher-util.c @@ -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; } diff --git a/src/launcher-util.h b/src/launcher-util.h index a3a704114..5fa9248dd 100644 --- a/src/launcher-util.h +++ b/src/launcher-util.h @@ -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 diff --git a/src/tty.c b/src/tty.c index f05f55bd1..2ac7236cf 100644 --- 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); diff --git a/src/weston-launch.c b/src/weston-launch.c index 80c06a817..87f46417c 100644 --- a/src/weston-launch.c +++ b/src/weston-launch.c @@ -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; + int len; - 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; - } - - 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; } diff --git a/src/weston-launch.h b/src/weston-launch.h index 5be013efc..e20c4c713 100644 --- a/src/weston-launch.h +++ b/src/weston-launch.h @@ -25,7 +25,12 @@ 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