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:
parent
fd83b6d70f
commit
409ef0a5c8
@ -34,6 +34,8 @@
|
||||
#include <assert.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
@ -83,6 +85,75 @@ wlsc_watch_process(struct wlsc_process *process)
|
||||
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
|
||||
surface_handle_buffer_destroy(struct wl_listener *listener,
|
||||
struct wl_resource *resource, uint32_t time)
|
||||
|
@ -418,12 +418,22 @@ uint32_t *
|
||||
wlsc_load_image(const char *filename,
|
||||
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 {
|
||||
pid_t pid;
|
||||
void (*cleanup)(struct wlsc_process *process, int status);
|
||||
wlsc_process_cleanup_func_t cleanup;
|
||||
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
|
||||
wlsc_data_device_manager_init(struct wlsc_compositor *compositor);
|
||||
void
|
||||
|
@ -27,9 +27,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/input.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <wayland-server.h>
|
||||
@ -880,44 +877,14 @@ static int
|
||||
launch_desktop_shell_process(struct wl_shell *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) {
|
||||
fprintf(stderr, "socketpair failed\n");
|
||||
shell->child.client = wlsc_client_launch(shell->compositor,
|
||||
&shell->child.process,
|
||||
shell_exe,
|
||||
desktop_shell_sigchld);
|
||||
|
||||
if (!shell->child.client)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "compositor.h"
|
||||
@ -369,43 +366,10 @@ static void
|
||||
launch_ux_daemon(struct tablet_shell *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) {
|
||||
fprintf(stderr, "socketpair failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
shell->client = wlsc_client_launch(shell->compositor,
|
||||
&shell->process,
|
||||
shell_exe, tablet_shell_sigchld);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user