summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Marler <johnnymarler@gmail.com>2021-03-27 09:55:59 -0600
committerDaniel Stone <daniels@collabora.com>2021-04-10 22:29:30 +0000
commitf153c494301901f2bf6ffa14b06f730478b1f20b (patch)
treea80cfc0cdd43c28901bc4dce58a0988a27ca7320
parent55f334cfdf149c408b4978b9f3bfd098ce856e2e (diff)
downloadweston-f153c494301901f2bf6ffa14b06f730478b1f20b.tar.gz
launcher: fix socket message race condition
fixes issue #484 (race condition with message to/from weston launch) The race condition occurs after weston sends the WESTON_LAUNCHER_OPEN message to weston-launch. The race is between when weston-launch replies with the fd handle versus weston-launch sending an activation message. If weston-launch sends an activation message before sending the fd handle, then weston will be in an invalid state. To fix this, I modified the fd handle reply that weston-launch sends to include a message id at the beginning, which I called WESTON_LAUNCHER_OPEN_REPLY. Along with this, weston now inspects the first part of any reply to determine whether it is an activation message or a reply to the OPEN message. In the newly handled case that it's an activation message, it tracks whether the latest result is a deactivate message and stores it in a flag to be handled once the open function has completed. Signed-off-by: Jonathan Marler <johnnymarler@gmail.com>
-rw-r--r--libweston/launcher-weston-launch.c75
-rw-r--r--libweston/weston-launch.c5
-rw-r--r--libweston/weston-launch.h2
3 files changed, 63 insertions, 19 deletions
diff --git a/libweston/launcher-weston-launch.c b/libweston/launcher-weston-launch.c
index c7db8da7..00cd1861 100644
--- a/libweston/launcher-weston-launch.c
+++ b/libweston/launcher-weston-launch.c
@@ -93,6 +93,7 @@ struct launcher_weston_launch {
struct wl_event_source *source;
int kb_mode, tty, drm_fd;
+ int deferred_deactivate;
};
static ssize_t
@@ -107,12 +108,36 @@ launcher_weston_launch_send(int sockfd, void *buf, size_t buflen)
return len;
}
+static void
+handle_deactivate(struct launcher_weston_launch *launcher)
+{
+ int reply;
+
+ launcher->compositor->session_active = false;
+ wl_signal_emit(&launcher->compositor->session_signal,
+ launcher->compositor);
+
+ reply = WESTON_LAUNCHER_DEACTIVATE_DONE;
+ launcher_weston_launch_send(launcher->fd, &reply, sizeof reply);
+}
+
+static void
+idle_deactivate(void *data)
+{
+ struct launcher_weston_launch *launcher = data;
+
+ if (launcher->deferred_deactivate) {
+ launcher->deferred_deactivate = 0;
+ handle_deactivate((struct launcher_weston_launch*)data);
+ }
+}
+
static int
launcher_weston_launch_open(struct weston_launcher *launcher_base,
const char *path, int flags)
{
struct launcher_weston_launch *launcher = wl_container_of(launcher_base, launcher, base);
- int n, ret;
+ int n;
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
@@ -120,6 +145,7 @@ launcher_weston_launch_open(struct weston_launcher *launcher_base,
char control[CMSG_SPACE(sizeof data->fd)];
ssize_t len;
struct weston_launcher_open *message;
+ struct { int id; int ret; } event;
n = sizeof(*message) + strlen(path) + 1;
message = malloc(n);
@@ -134,19 +160,33 @@ launcher_weston_launch_open(struct weston_launcher *launcher_base,
free(message);
memset(&msg, 0, sizeof msg);
- iov.iov_base = &ret;
- iov.iov_len = sizeof ret;
+ iov.iov_base = &event;
+ iov.iov_len = sizeof event;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
- msg.msg_controllen = sizeof control;
- do {
- len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
- } while (len < 0 && errno == EINTR);
+ while (1) {
+ msg.msg_controllen = sizeof control;
+
+ do {
+ len = recvmsg(launcher->fd, &msg, MSG_CMSG_CLOEXEC);
+ } while (len < 0 && errno == EINTR);
+
+ // Only OPEN_REPLY and up to one DEACTIVATE message should be possible here
+ if ((len == sizeof event) && (event.id == WESTON_LAUNCHER_OPEN_REPLY))
+ break;
+
+ if ((len == sizeof event.id) && (event.id == WESTON_LAUNCHER_DEACTIVATE) && (launcher->deferred_deactivate == 0)) {
+ wl_event_loop_add_idle(wl_display_get_event_loop(launcher->compositor->wl_display), idle_deactivate, launcher);
+ launcher->deferred_deactivate = 1;
+ } else {
+ weston_log("unexpected event %d (len=%zd) from weston-launch\n", event.id, len);
+ return -1;
+ }
+ }
- if (len != sizeof ret ||
- ret < 0)
+ if (event.ret < 0)
return -1;
cmsg = CMSG_FIRSTHDR(&msg);
@@ -201,7 +241,7 @@ static int
launcher_weston_launch_data(int fd, uint32_t mask, void *data)
{
struct launcher_weston_launch *launcher = data;
- int len, ret, reply;
+ int len, ret;
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
weston_log("launcher socket closed, exiting\n");
@@ -212,6 +252,12 @@ launcher_weston_launch_data(int fd, uint32_t mask, void *data)
exit(-1);
}
+ if (launcher->deferred_deactivate) {
+ launcher->deferred_deactivate = 0;
+ handle_deactivate(launcher);
+ return 1;
+ }
+
do {
len = recv(launcher->fd, &ret, sizeof ret, 0);
} while (len < 0 && errno == EINTR);
@@ -223,13 +269,7 @@ launcher_weston_launch_data(int fd, uint32_t mask, void *data)
launcher->compositor);
break;
case WESTON_LAUNCHER_DEACTIVATE:
- launcher->compositor->session_active = false;
- wl_signal_emit(&launcher->compositor->session_signal,
- launcher->compositor);
-
- reply = WESTON_LAUNCHER_DEACTIVATE_DONE;
- launcher_weston_launch_send(launcher->fd, &reply, sizeof reply);
-
+ handle_deactivate(launcher);
break;
default:
weston_log("unexpected event from weston-launch\n");
@@ -287,6 +327,7 @@ launcher_weston_launch_connect(struct weston_launcher **out, struct weston_compo
* (struct launcher_weston_launch **) out = launcher;
launcher->compositor = compositor;
launcher->drm_fd = -1;
+ launcher->deferred_deactivate = 0;
launcher->fd = launcher_weston_environment_get_fd("WESTON_LAUNCHER_SOCK");
if (launcher->fd != -1) {
launcher->tty = launcher_weston_environment_get_fd("WESTON_TTY_FD");
diff --git a/libweston/weston-launch.c b/libweston/weston-launch.c
index 521cb2cb..c43ed7b2 100644
--- a/libweston/weston-launch.c
+++ b/libweston/weston-launch.c
@@ -377,8 +377,9 @@ err0:
nmsg.msg_controllen = cmsg->cmsg_len;
ret = 0;
}
- iov.iov_base = &ret;
- iov.iov_len = sizeof ret;
+ struct { int reply_id; int ret; } reply_iov_data = { WESTON_LAUNCHER_OPEN_REPLY, ret };
+ iov.iov_base = &reply_iov_data;
+ iov.iov_len = sizeof reply_iov_data;
if (wl->verbose)
fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n",
diff --git a/libweston/weston-launch.h b/libweston/weston-launch.h
index 575d2cf9..ee322601 100644
--- a/libweston/weston-launch.h
+++ b/libweston/weston-launch.h
@@ -35,6 +35,8 @@ enum weston_launcher_event {
WESTON_LAUNCHER_ACTIVATE,
WESTON_LAUNCHER_DEACTIVATE,
WESTON_LAUNCHER_DEACTIVATE_DONE,
+ // This event is followed by an fd handle
+ WESTON_LAUNCHER_OPEN_REPLY,
};
struct weston_launcher_message {