Move the functions launching clients to main.c
They belong in the compositor rather than libweston since they
set signals handlers, and a library should not do that behind its
user's back. Besides, they were using functions in main.c already
so they were not usable by other compositors.
Signed-off-by: Giulio Camuffo <giuliocamuffo@gmail.com>
Reviewed-by: Quentin Glidic <sardemff7+git@sardemff7.net>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
diff --git a/src/main.c b/src/main.c
index 39a13cf..2251101 100644
--- a/src/main.c
+++ b/src/main.c
@@ -37,6 +37,7 @@
#include <sys/utsname.h>
#include <sys/stat.h>
#include <sys/wait.h>
+#include <sys/socket.h>
#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
@@ -48,6 +49,7 @@
#include "../shared/helpers.h"
#include "git-version.h"
#include "version.h"
+#include "weston.h"
#include "compositor-drm.h"
#include "compositor-headless.h"
@@ -168,12 +170,156 @@
#endif
+static void
+child_client_exec(int sockfd, const char *path)
+{
+ int clientfd;
+ char s[32];
+ sigset_t allsigs;
+
+ /* do not give our signal mask to the new process */
+ sigfillset(&allsigs);
+ sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
+
+ /* Launch clients as the user. Do not lauch clients with wrong euid.*/
+ if (seteuid(getuid()) == -1) {
+ weston_log("compositor: failed seteuid\n");
+ return;
+ }
+
+ /* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
+ * non-CLOEXEC fd to pass through exec. */
+ clientfd = dup(sockfd);
+ if (clientfd == -1) {
+ weston_log("compositor: dup failed: %m\n");
+ return;
+ }
+
+ snprintf(s, sizeof s, "%d", clientfd);
+ setenv("WAYLAND_SOCKET", s, 1);
+
+ if (execl(path, path, NULL) < 0)
+ weston_log("compositor: executing '%s' failed: %m\n",
+ path);
+}
+
+WL_EXPORT struct wl_client *
+weston_client_launch(struct weston_compositor *compositor,
+ struct weston_process *proc,
+ const char *path,
+ weston_process_cleanup_func_t cleanup)
+{
+ int sv[2];
+ pid_t pid;
+ struct wl_client *client;
+
+ weston_log("launching '%s'\n", path);
+
+ if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
+ weston_log("weston_client_launch: "
+ "socketpair failed while launching '%s': %m\n",
+ path);
+ return NULL;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ close(sv[0]);
+ close(sv[1]);
+ weston_log("weston_client_launch: "
+ "fork failed while launching '%s': %m\n", path);
+ return NULL;
+ }
+
+ if (pid == 0) {
+ child_client_exec(sv[1], path);
+ _exit(-1);
+ }
+
+ close(sv[1]);
+
+ client = wl_client_create(compositor->wl_display, sv[0]);
+ if (!client) {
+ close(sv[0]);
+ weston_log("weston_client_launch: "
+ "wl_client_create failed while launching '%s'.\n",
+ path);
+ return NULL;
+ }
+
+ proc->pid = pid;
+ proc->cleanup = cleanup;
+ weston_watch_process(proc);
+
+ return client;
+}
+
WL_EXPORT void
weston_watch_process(struct weston_process *process)
{
wl_list_insert(&child_process_list, &process->link);
}
+struct process_info {
+ struct weston_process proc;
+ char *path;
+};
+
+static void
+process_handle_sigchld(struct weston_process *process, int status)
+{
+ struct process_info *pinfo =
+ container_of(process, struct process_info, proc);
+
+ /*
+ * There are no guarantees whether this runs before or after
+ * the wl_client destructor.
+ */
+
+ if (WIFEXITED(status)) {
+ weston_log("%s exited with status %d\n", pinfo->path,
+ WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ weston_log("%s died on signal %d\n", pinfo->path,
+ WTERMSIG(status));
+ } else {
+ weston_log("%s disappeared\n", pinfo->path);
+ }
+
+ free(pinfo->path);
+ free(pinfo);
+}
+
+WL_EXPORT struct wl_client *
+weston_client_start(struct weston_compositor *compositor, const char *path)
+{
+ struct process_info *pinfo;
+ struct wl_client *client;
+
+ pinfo = zalloc(sizeof *pinfo);
+ if (!pinfo)
+ return NULL;
+
+ pinfo->path = strdup(path);
+ if (!pinfo->path)
+ goto out_free;
+
+ client = weston_client_launch(compositor, &pinfo->proc, path,
+ process_handle_sigchld);
+ if (!client)
+ goto out_str;
+
+ return client;
+
+out_str:
+ free(pinfo->path);
+
+out_free:
+ free(pinfo);
+
+ return NULL;
+}
+
static void
log_uname(void)
{