compositor: refactor client forking code
authorPekka Paalanen <ppaalanen@gmail.com>
Fri, 2 Dec 2011 13:30:21 +0000 (15:30 +0200)
committerPekka Paalanen <ppaalanen@gmail.com>
Thu, 8 Dec 2011 08:42:00 +0000 (10:42 +0200)
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>
compositor/compositor.c
compositor/compositor.h
compositor/shell.c
compositor/tablet-shell.c

index 2c04c3b..79440fd 100644 (file)
@@ -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>
@@ -84,6 +86,75 @@ wlsc_watch_process(struct wlsc_process *process)
 }
 
 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)
 {
index 1d55158..7f1dd74 100644 (file)
@@ -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
index b7cfdd3..e104941 100644 (file)
@@ -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");
-               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);
+       shell->child.client = wlsc_client_launch(shell->compositor,
+                                                &shell->child.process,
+                                                shell_exe,
+                                                desktop_shell_sigchld);
 
-               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__);
+       if (!shell->child.client)
                return -1;
-       }
        return 0;
 }
 
index 416a971..6901acd 100644 (file)
@@ -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