compositor: refactor client forking code
shell.c and tablet-shell.c had almost the same code for forking their special shell client. Generalise this code and put it into wlsc_client_launch() in compositor.c. Improve error cleanup and reporting in wlsc_client_launch(). Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
This commit is contained in:
@@ -34,6 +34,8 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -83,6 +85,75 @@ wlsc_watch_process(struct wlsc_process *process)
|
|||||||
wl_list_insert(&child_process_list, &process->link);
|
wl_list_insert(&child_process_list, &process->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
child_client_exec(int sockfd, const char *path)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
char s[32];
|
||||||
|
|
||||||
|
/* SOCK_CLOEXEC closes both ends, so we need to unset
|
||||||
|
* the flag on the client fd. */
|
||||||
|
flags = fcntl(sockfd, F_GETFD);
|
||||||
|
if (flags != -1)
|
||||||
|
fcntl(sockfd, F_SETFD, flags & ~FD_CLOEXEC);
|
||||||
|
|
||||||
|
snprintf(s, sizeof s, "%d", sockfd);
|
||||||
|
setenv("WAYLAND_SOCKET", s, 1);
|
||||||
|
|
||||||
|
if (execl(path, path, NULL) < 0)
|
||||||
|
fprintf(stderr, "compositor: executing '%s' failed: %m\n",
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
|
||||||
|
WL_EXPORT struct wl_client *
|
||||||
|
wlsc_client_launch(struct wlsc_compositor *compositor,
|
||||||
|
struct wlsc_process *proc,
|
||||||
|
const char *path,
|
||||||
|
wlsc_process_cleanup_func_t cleanup)
|
||||||
|
{
|
||||||
|
int sv[2];
|
||||||
|
pid_t pid;
|
||||||
|
struct wl_client *client;
|
||||||
|
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
|
||||||
|
fprintf(stderr, "wlsc_client_launch: "
|
||||||
|
"socketpair failed while launching '%s': %m\n",
|
||||||
|
path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
close(sv[0]);
|
||||||
|
close(sv[1]);
|
||||||
|
fprintf(stderr, "wlsc_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]);
|
||||||
|
fprintf(stderr, "wlsc_client_launch: "
|
||||||
|
"wl_client_create failed while launching '%s'.\n",
|
||||||
|
path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc->pid = pid;
|
||||||
|
proc->cleanup = cleanup;
|
||||||
|
wlsc_watch_process(proc);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
surface_handle_buffer_destroy(struct wl_listener *listener,
|
surface_handle_buffer_destroy(struct wl_listener *listener,
|
||||||
struct wl_resource *resource, uint32_t time)
|
struct wl_resource *resource, uint32_t time)
|
||||||
|
|||||||
+11
-1
@@ -418,12 +418,22 @@ uint32_t *
|
|||||||
wlsc_load_image(const char *filename,
|
wlsc_load_image(const char *filename,
|
||||||
int32_t *width_arg, int32_t *height_arg, uint32_t *stride_arg);
|
int32_t *width_arg, int32_t *height_arg, uint32_t *stride_arg);
|
||||||
|
|
||||||
|
struct wlsc_process;
|
||||||
|
typedef void (*wlsc_process_cleanup_func_t)(struct wlsc_process *process,
|
||||||
|
int status);
|
||||||
|
|
||||||
struct wlsc_process {
|
struct wlsc_process {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
void (*cleanup)(struct wlsc_process *process, int status);
|
wlsc_process_cleanup_func_t cleanup;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct wl_client *
|
||||||
|
wlsc_client_launch(struct wlsc_compositor *compositor,
|
||||||
|
struct wlsc_process *proc,
|
||||||
|
const char *path,
|
||||||
|
wlsc_process_cleanup_func_t cleanup);
|
||||||
|
|
||||||
int
|
int
|
||||||
wlsc_data_device_manager_init(struct wlsc_compositor *compositor);
|
wlsc_data_device_manager_init(struct wlsc_compositor *compositor);
|
||||||
void
|
void
|
||||||
|
|||||||
+6
-39
@@ -27,9 +27,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
@@ -880,44 +877,14 @@ static int
|
|||||||
launch_desktop_shell_process(struct wl_shell *shell)
|
launch_desktop_shell_process(struct wl_shell *shell)
|
||||||
{
|
{
|
||||||
const char *shell_exe = LIBEXECDIR "/wayland-desktop-shell";
|
const char *shell_exe = LIBEXECDIR "/wayland-desktop-shell";
|
||||||
struct wlsc_compositor *compositor = shell->compositor;
|
|
||||||
char s[32];
|
|
||||||
int sv[2], flags;
|
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
|
shell->child.client = wlsc_client_launch(shell->compositor,
|
||||||
fprintf(stderr, "socketpair failed\n");
|
&shell->child.process,
|
||||||
|
shell_exe,
|
||||||
|
desktop_shell_sigchld);
|
||||||
|
|
||||||
|
if (!shell->child.client)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
shell->child.process.pid = fork();
|
|
||||||
shell->child.process.cleanup = desktop_shell_sigchld;
|
|
||||||
|
|
||||||
switch (shell->child.process.pid) {
|
|
||||||
case 0:
|
|
||||||
/* SOCK_CLOEXEC closes both ends, so we need to unset
|
|
||||||
* the flag on the client fd. */
|
|
||||||
flags = fcntl(sv[1], F_GETFD);
|
|
||||||
if (flags != -1)
|
|
||||||
fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
|
|
||||||
|
|
||||||
snprintf(s, sizeof s, "%d", sv[1]);
|
|
||||||
setenv("WAYLAND_SOCKET", s, 1);
|
|
||||||
if (execl(shell_exe, shell_exe, NULL) < 0)
|
|
||||||
fprintf(stderr, "%s: running '%s' failed: %m\n",
|
|
||||||
__func__, shell_exe);
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
default:
|
|
||||||
close(sv[1]);
|
|
||||||
shell->child.client =
|
|
||||||
wl_client_create(compositor->wl_display, sv[0]);
|
|
||||||
wlsc_watch_process(&shell->child.process);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
fprintf(stderr, "%s: fork failed: %m\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
@@ -369,43 +366,10 @@ static void
|
|||||||
launch_ux_daemon(struct tablet_shell *shell)
|
launch_ux_daemon(struct tablet_shell *shell)
|
||||||
{
|
{
|
||||||
const char *shell_exe = LIBEXECDIR "/wayland-tablet-shell";
|
const char *shell_exe = LIBEXECDIR "/wayland-tablet-shell";
|
||||||
struct wlsc_compositor *compositor = shell->compositor;
|
|
||||||
char s[32];
|
|
||||||
int sv[2], flags;
|
|
||||||
|
|
||||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
|
shell->client = wlsc_client_launch(shell->compositor,
|
||||||
fprintf(stderr, "socketpair failed\n");
|
&shell->process,
|
||||||
return;
|
shell_exe, tablet_shell_sigchld);
|
||||||
}
|
|
||||||
|
|
||||||
shell->process.pid = fork();
|
|
||||||
shell->process.cleanup = tablet_shell_sigchld;
|
|
||||||
|
|
||||||
switch (shell->process.pid) {
|
|
||||||
case 0:
|
|
||||||
/* SOCK_CLOEXEC closes both ends, so we need to unset
|
|
||||||
* the flag on the client fd. */
|
|
||||||
flags = fcntl(sv[1], F_GETFD);
|
|
||||||
if (flags != -1)
|
|
||||||
fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
|
|
||||||
|
|
||||||
snprintf(s, sizeof s, "%d", sv[1]);
|
|
||||||
setenv("WAYLAND_SOCKET", s, 1);
|
|
||||||
if (execl(shell_exe, shell_exe, NULL) < 0)
|
|
||||||
fprintf(stderr, "exec failed: %m\n");
|
|
||||||
exit(-1);
|
|
||||||
|
|
||||||
default:
|
|
||||||
close(sv[1]);
|
|
||||||
shell->client =
|
|
||||||
wl_client_create(compositor->wl_display, sv[0]);
|
|
||||||
wlsc_watch_process(&shell->process);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case -1:
|
|
||||||
fprintf(stderr, "failed to fork\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user