Skip to content
Commits on Source (27)
......@@ -43,7 +43,7 @@
variables:
FDO_UPSTREAM_REPO: wayland/weston
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
FDO_DISTRIBUTION_TAG: '2023-06-12-kernel-mesa-upgrade-2'
FDO_DISTRIBUTION_TAG: '2023-07-19-bump-wayland-to-1.22'
include:
......
......@@ -105,7 +105,7 @@ fi
# Build and install Wayland; keep this version in sync with our dependency
# in meson.build.
git clone --branch 1.20.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
cd wayland
git show -s HEAD
mkdir build
......
#!/bin/bash
export LSAN_OPTIONS="suppressions=../.gitlab-ci/leak-sanitizer.supp"
export ASAN_OPTIONS="detect_leaks=0"
export ASAN_OPTIONS="detect_leaks=1"
exec "$@"
......@@ -53,6 +53,7 @@
#include "shared/helpers.h"
#include "shared/process-util.h"
#include "shared/string-helpers.h"
#include "shared/xalloc.h"
#include "git-version.h"
#include <libweston/version.h>
#include "weston.h"
......@@ -334,10 +335,20 @@ to_wet_compositor(struct weston_compositor *compositor)
return weston_compositor_get_user_data(compositor);
}
WL_EXPORT void
wet_process_destroy(struct wet_process *process, int status, bool call_cleanup)
{
wl_list_remove(&process->link);
if (call_cleanup && process->cleanup)
process->cleanup(process, status, process->cleanup_data);
free(process->path);
free(process);
}
static int
sigchld_handler(int signal_number, void *data)
{
struct weston_process *p;
struct wet_process *p;
struct wet_compositor *wet = data;
int status;
pid_t pid;
......@@ -359,9 +370,17 @@ sigchld_handler(int signal_number, void *data)
if (&p->link == &wet->child_process_list)
continue;
wl_list_remove(&p->link);
wl_list_init(&p->link);
p->cleanup(p, status);
if (WIFEXITED(status)) {
weston_log("%s exited with status %d\n", p->path,
WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
weston_log("%s died on signal %d\n", p->path,
WTERMSIG(status));
} else {
weston_log("%s disappeared\n", p->path);
}
wet_process_destroy(p, status, true);
}
if (pid < 0 && errno != ECHILD)
......@@ -387,14 +406,16 @@ cleanup_for_child_process() {
sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
}
WL_EXPORT bool
weston_client_launch(struct weston_compositor *compositor,
struct weston_process *proc,
struct custom_env *child_env,
int *no_cloexec_fds,
size_t num_no_cloexec_fds,
weston_process_cleanup_func_t cleanup)
WL_EXPORT struct wet_process *
wet_client_launch(struct weston_compositor *compositor,
struct custom_env *child_env,
int *no_cloexec_fds,
size_t num_no_cloexec_fds,
wet_process_cleanup_func_t cleanup,
void *cleanup_data)
{
struct wet_compositor *wet = to_wet_compositor(compositor);
struct wet_process *proc = NULL;
const char *fail_cloexec = "Couldn't unset CLOEXEC on child FDs";
const char *fail_seteuid = "Couldn't call seteuid";
char *fail_exec;
......@@ -402,7 +423,6 @@ weston_client_launch(struct weston_compositor *compositor,
char * const *envp;
pid_t pid;
int err;
bool ret;
size_t i;
size_t written __attribute__((unused));
......@@ -441,88 +461,42 @@ weston_client_launch(struct weston_compositor *compositor,
_exit(EXIT_FAILURE);
default:
proc = xzalloc(sizeof(*proc));
proc->pid = pid;
proc->cleanup = cleanup;
wet_watch_process(compositor, proc);
ret = true;
proc->cleanup_data = cleanup_data;
proc->path = strdup(argp[0]);
wl_list_insert(&wet->child_process_list, &proc->link);
break;
case -1:
weston_log("weston_client_launch: "
"fork failed while launching '%s': %s\n", argp[0],
strerror(errno));
ret = false;
break;
}
custom_env_fini(child_env);
free(fail_exec);
return ret;
}
WL_EXPORT void
wet_watch_process(struct weston_compositor *compositor,
struct weston_process *process)
{
struct wet_compositor *wet = to_wet_compositor(compositor);
wl_list_insert(&wet->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);
return proc;
}
WL_EXPORT struct wl_client *
weston_client_start(struct weston_compositor *compositor, const char *path)
wet_client_start(struct weston_compositor *compositor, const char *path)
{
struct process_info *pinfo;
struct wet_process *proc;
struct wl_client *client;
struct custom_env child_env;
struct fdstr wayland_socket = FDSTR_INIT;
int no_cloexec_fds[1];
size_t num_no_cloexec_fds = 0;
bool ret;
pinfo = zalloc(sizeof *pinfo);
if (!pinfo)
return NULL;
pinfo->path = strdup(path);
if (!pinfo->path)
goto out_free;
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0,
wayland_socket.fds) < 0) {
weston_log("weston_client_start: "
weston_log("wet_client_start: "
"socketpair failed while launching '%s': %s\n",
path, strerror(errno));
goto out_path;
return NULL;
}
custom_env_init_from_environ(&child_env);
......@@ -535,18 +509,18 @@ weston_client_start(struct weston_compositor *compositor, const char *path)
assert(num_no_cloexec_fds <= ARRAY_LENGTH(no_cloexec_fds));
ret = weston_client_launch(compositor, &pinfo->proc, &child_env,
no_cloexec_fds, num_no_cloexec_fds,
process_handle_sigchld);
if (!ret)
goto out_path;
proc = wet_client_launch(compositor, &child_env,
no_cloexec_fds, num_no_cloexec_fds,
NULL, NULL);
if (!proc)
return NULL;
client = wl_client_create(compositor->wl_display,
wayland_socket.fds[0]);
if (!client) {
weston_log("weston_client_start: "
"wl_client_create failed while launching '%s'.\n",
path);
weston_log("wet_client_start: "
"wl_client_create failed while launching '%s'.\n",
path);
/* We have no way of killing the process, so leave it hanging */
goto out_sock;
}
......@@ -554,12 +528,10 @@ weston_client_start(struct weston_compositor *compositor, const char *path)
/* Close the child end of our socket which we no longer need */
close(wayland_socket.fds[1]);
/* proc is now owned by the compositor's process list */
return client;
out_path:
free(pinfo->path);
out_free:
free(pinfo);
out_sock:
fdstr_close_all(&wayland_socket);
......@@ -3768,10 +3740,10 @@ copy_command_line(int argc, char * const argv[])
}
#if !defined(BUILD_XWAYLAND)
int
void *
wet_load_xwayland(struct weston_compositor *comp)
{
return -1;
return NULL;
}
#endif
......@@ -3910,6 +3882,8 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
struct weston_log_context *log_ctx = NULL;
struct weston_log_subscriber *logger = NULL;
struct weston_log_subscriber *flight_rec = NULL;
struct wet_process *process, *process_tmp;
void *wet_xwl = NULL;
sigset_t mask;
struct sigaction action;
......@@ -4164,7 +4138,8 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
false);
}
if (xwayland) {
if (wet_load_xwayland(wet.compositor) < 0)
wet_xwl = wet_load_xwayland(wet.compositor);
if (!wet_xwl)
goto out;
}
......@@ -4216,11 +4191,17 @@ out:
if (protologger)
wl_protocol_logger_destroy(protologger);
if (wet_xwl)
wet_xwayland_destroy(wet.compositor, wet_xwl);
weston_compositor_destroy(wet.compositor);
wet_compositor_destroy_layout(&wet);
weston_log_scope_destroy(protocol_scope);
protocol_scope = NULL;
wl_list_for_each_safe(process, process_tmp, &wet.child_process_list, link)
wet_process_destroy(process, 0, false);
out_signals:
for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
if (signals[i])
......
......@@ -988,7 +988,9 @@ input_method_client_notifier(struct wl_listener *listener, void *data)
client_listener);
text_backend->input_method.client = NULL;
respawn_input_method_process(text_backend);
if (!text_backend->compositor->shutting_down)
respawn_input_method_process(text_backend);
}
static void
......@@ -1006,8 +1008,8 @@ launch_input_method(void *data)
setenv("WESTON_KEYBOARD_SURFACE_TYPE", "overlay", 1);
text_backend->input_method.client =
weston_client_start(text_backend->compositor,
text_backend->input_method.path);
wet_client_start(text_backend->compositor,
text_backend->input_method.path);
if (!text_backend->input_method.client) {
weston_log("not able to start %s\n",
......
......@@ -69,8 +69,7 @@ screenshooter_binding(struct weston_keyboard *keyboard,
return;
}
shooter->client = weston_client_start(shooter->ec,
screenshooter_exe);
shooter->client = wet_client_start(shooter->ec, screenshooter_exe);
free(screenshooter_exe);
if (!shooter->client)
......
......@@ -36,32 +36,34 @@ extern "C" {
void
screenshooter_create(struct weston_compositor *ec);
struct weston_process;
typedef void (*weston_process_cleanup_func_t)(struct weston_process *process,
int status);
struct wet_process;
typedef void (*wet_process_cleanup_func_t)(struct wet_process *process,
int status,
void *data);
struct weston_process {
struct wet_process {
pid_t pid;
weston_process_cleanup_func_t cleanup;
char *path;
wet_process_cleanup_func_t cleanup;
void *cleanup_data;
struct wl_list link;
};
struct custom_env;
bool
weston_client_launch(struct weston_compositor *compositor,
struct weston_process *proc,
struct custom_env *custom_env,
int *fds_no_cloexec,
size_t num_fds_no_cloexec,
weston_process_cleanup_func_t cleanup);
struct wet_process *
wet_client_launch(struct weston_compositor *compositor,
struct custom_env *custom_env,
int *fds_no_cloexec,
size_t num_fds_no_cloexec,
wet_process_cleanup_func_t cleanup,
void *cleanup_data);
struct wl_client *
weston_client_start(struct weston_compositor *compositor, const char *path);
wet_client_start(struct weston_compositor *compositor, const char *path);
void
wet_watch_process(struct weston_compositor *compositor,
struct weston_process *process);
wet_process_destroy(struct wet_process *process, int status, bool call_cleanup);
struct weston_config *
wet_get_config(struct weston_compositor *compositor);
......@@ -86,9 +88,12 @@ wet_get_libexec_path(const char *name);
char *
wet_get_bindir_path(const char *name);
int
void *
wet_load_xwayland(struct weston_compositor *comp);
void
wet_xwayland_destroy(struct weston_compositor *comp, void *data);
struct text_backend;
struct text_backend *
......
......@@ -48,13 +48,11 @@
struct wet_xwayland {
struct weston_compositor *compositor;
struct wl_listener compositor_destroy_listener;
const struct weston_xwayland_api *api;
struct weston_xwayland *xwayland;
struct wl_event_source *display_fd_source;
struct wl_client *client;
int wm_fd;
struct weston_process process;
struct wet_process *process;
};
static int
......@@ -82,7 +80,7 @@ handle_display_fd(int fd, uint32_t mask, void *data)
if (n <= 0 || (n > 0 && buf[n - 1] != '\n'))
return 1;
wxw->api->xserver_loaded(wxw->xwayland, wxw->client, wxw->wm_fd);
wxw->api->xserver_loaded(wxw->xwayland, wxw->wm_fd);
out:
wl_event_source_remove(wxw->display_fd_source);
......@@ -92,16 +90,19 @@ out:
}
static void
xserver_cleanup(struct weston_process *process, int status)
xserver_cleanup(struct wet_process *process, int status, void *data)
{
struct wet_xwayland *wxw =
container_of(process, struct wet_xwayland, process);
struct wet_xwayland *wxw = data;
/* We only have one Xwayland process active, so make sure it's the
* right one */
assert(process == wxw->process);
wxw->api->xserver_exited(wxw->xwayland, status);
wxw->client = NULL;
wxw->api->xserver_exited(wxw->xwayland);
wxw->process = NULL;
}
static pid_t
static struct wl_client *
spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd)
{
struct wet_xwayland *wxw = user_data;
......@@ -113,11 +114,11 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
char *xserver = NULL;
struct weston_config *config = wet_get_config(wxw->compositor);
struct weston_config_section *section;
struct wl_client *client;
struct wl_event_loop *loop;
struct custom_env child_env;
int no_cloexec_fds[5];
size_t num_no_cloexec_fds = 0;
int ret;
size_t written __attribute__ ((unused));
if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, wayland_socket.fds) < 0) {
......@@ -168,19 +169,20 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
custom_env_add_arg(&child_env, x11_wm_socket.str1);
custom_env_add_arg(&child_env, "-terminate");
ret = weston_client_launch(wxw->compositor, &wxw->process, &child_env,
no_cloexec_fds, num_no_cloexec_fds,
xserver_cleanup);
if (!ret) {
wxw->process =
wet_client_launch(wxw->compositor, &child_env,
no_cloexec_fds, num_no_cloexec_fds,
xserver_cleanup, wxw);
if (!wxw->process) {
weston_log("Couldn't start Xwayland\n");
goto err;
}
wxw->client = wl_client_create(wxw->compositor->wl_display,
wayland_socket.fds[0]);
if (!wxw->client) {
client = wl_client_create(wxw->compositor->wl_display,
wayland_socket.fds[0]);
if (!client) {
weston_log("Couldn't create client for Xwayland\n");
goto err;
goto err_proc;
}
wxw->wm_fd = x11_wm_socket.fds[0];
......@@ -202,34 +204,34 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
free(xserver);
return wxw->process.pid;
return client;
err_proc:
wl_list_remove(&wxw->process->link);
err:
free(xserver);
fdstr_close_all(&display_pipe);
fdstr_close_all(&x11_wm_socket);
fdstr_close_all(&wayland_socket);
return -1;
free(wxw->process);
return NULL;
}
static void
wxw_compositor_destroy(struct wl_listener *listener, void *data)
void
wet_xwayland_destroy(struct weston_compositor *comp, void *data)
{
struct wet_xwayland *wxw =
wl_container_of(listener, wxw, compositor_destroy_listener);
wl_list_remove(&wxw->compositor_destroy_listener.link);
struct wet_xwayland *wxw = data;
/* Don't call xserver_exited because Xwayland's own destroy handler
* already does this for us ... */
if (wxw->client)
kill(wxw->process.pid, SIGTERM);
/* Calling this will call the process cleanup, in turn cleaning up the
* client and the core Xwayland state */
if (wxw->process)
wet_process_destroy(wxw->process, 0, true);
wl_list_remove(&wxw->process.link);
free(wxw);
}
int
void *
wet_load_xwayland(struct weston_compositor *comp)
{
const struct weston_xwayland_api *api;
......@@ -237,34 +239,29 @@ wet_load_xwayland(struct weston_compositor *comp)
struct wet_xwayland *wxw;
if (weston_compositor_load_xwayland(comp) < 0)
return -1;
return NULL;
api = weston_xwayland_get_api(comp);
if (!api) {
weston_log("Failed to get the xwayland module API.\n");
return -1;
return NULL;
}
xwayland = api->get(comp);
if (!xwayland) {
weston_log("Failed to get the xwayland object.\n");
return -1;
return NULL;
}
wxw = zalloc(sizeof *wxw);
if (!wxw)
return -1;
return NULL;
wxw->compositor = comp;
wxw->api = api;
wxw->xwayland = xwayland;
wl_list_init(&wxw->process.link);
wxw->process.cleanup = xserver_cleanup;
wxw->compositor_destroy_listener.notify = wxw_compositor_destroy;
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
return -1;
return NULL;
wl_signal_add(&comp->destroy_signal, &wxw->compositor_destroy_listener);
return 0;
return wxw;
}
......@@ -4359,8 +4359,10 @@ desktop_shell_client_destroy(struct wl_listener *listener, void *data)
* returning.
*/
if (!check_desktop_shell_crash_too_early(shell))
if (!shell->compositor->shutting_down &&
!check_desktop_shell_crash_too_early(shell)) {
respawn_desktop_shell_process(shell);
}
shell_fade_startup(shell);
}
......@@ -4370,8 +4372,8 @@ launch_desktop_shell_process(void *data)
{
struct desktop_shell *shell = data;
shell->child.client = weston_client_start(shell->compositor,
shell->client);
shell->child.client = wet_client_start(shell->compositor,
shell->client);
if (!shell->child.client) {
weston_log("not able to start %s\n", shell->client);
......
......@@ -1366,6 +1366,7 @@ struct weston_renderer;
*/
struct weston_compositor {
struct wl_signal destroy_signal;
bool shutting_down;
struct wl_display *wl_display;
struct weston_desktop_xwayland *xwayland;
......
......@@ -37,10 +37,10 @@ extern "C" {
struct weston_compositor;
struct weston_xwayland;
#define WESTON_XWAYLAND_API_NAME "weston_xwayland_v1"
#define WESTON_XWAYLAND_API_NAME "weston_xwayland_v3"
#define WESTON_XWAYLAND_SURFACE_API_NAME "weston_xwayland_surface_v1"
typedef pid_t
typedef struct wl_client *
(*weston_xwayland_spawn_xserver_func_t)(
void *user_data, const char *display, int abstract_fd, int unix_fd);
......@@ -83,19 +83,16 @@ struct weston_xwayland_api {
/** Notify the Xwayland module that the Xwayland server is loaded.
*
* After the Xwayland server process has been spawned it will notify
* the parent that is has finished the initialization by sending a
* SIGUSR1 signal.
* The caller should listen for that signal and call this function
* the parent that it has finished the initialization by writing to
* the displayfd passed.
* The caller should listen for that write and call this function
* when it is received.
*
* \param xwayland The Xwayland context object.
* \param client The wl_client object representing the connection of
* the Xwayland server process.
* \param wm_fd The file descriptor for the wm.
*/
void
(*xserver_loaded)(struct weston_xwayland *xwayland,
struct wl_client *client, int wm_fd);
(*xserver_loaded)(struct weston_xwayland *xwayland, int wm_fd);
/** Notify the Xwayland module that the Xwayland server has exited.
*
......@@ -105,10 +102,9 @@ struct weston_xwayland_api {
* socket, and may call the spawn function again.
*
* \param xwayland The Xwayland context object.
* \param exit_status The exit status of the Xwayland server process.
*/
void
(*xserver_exited)(struct weston_xwayland *xwayland, int exit_status);
(*xserver_exited)(struct weston_xwayland *xwayland);
};
/** Retrieve the API object for the libweston Xwayland module.
......
......@@ -2101,8 +2101,8 @@ launch_hmi_client_process(void *data)
(struct hmi_controller *)data;
hmi_ctrl->user_interface =
weston_client_start(hmi_ctrl->compositor,
hmi_ctrl->hmi_setting->ivi_homescreen);
wet_client_start(hmi_ctrl->compositor,
hmi_ctrl->hmi_setting->ivi_homescreen);
free(hmi_ctrl->hmi_setting->ivi_homescreen);
}
......
......@@ -285,7 +285,7 @@ drm_output_fini_egl(struct drm_output *output)
/* Destroying the GBM surface will destroy all our GBM buffers,
* regardless of refcount. Ensure we destroy them here. */
if (!b->shutting_down &&
if (!b->compositor->shutting_down &&
output->scanout_plane->state_cur->fb &&
output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
drm_plane_reset_state(output->scanout_plane);
......
......@@ -374,8 +374,6 @@ struct drm_backend {
uint32_t pageflip_timeout;
bool shutting_down;
struct weston_log_scope *debug;
};
......
......@@ -1490,7 +1490,7 @@ drm_output_fini_pixman(struct drm_output *output)
/* Destroying the Pixman surface will destroy all our buffers,
* regardless of refcount. Ensure we destroy them here. */
if (!b->shutting_down &&
if (!b->compositor->shutting_down &&
output->scanout_plane->state_cur->fb &&
output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) {
drm_plane_reset_state(output->scanout_plane);
......@@ -1970,7 +1970,7 @@ drm_output_deinit_planes(struct drm_output *output)
/* If the compositor is already shutting down, the planes have already
* been destroyed. */
if (!b->shutting_down) {
if (!b->compositor->shutting_down) {
wl_list_remove(&output->scanout_plane->base.link);
wl_list_init(&output->scanout_plane->base.link);
......@@ -2173,7 +2173,7 @@ drm_output_deinit(struct weston_output *base)
struct drm_device *device = b->drm;
struct drm_pending_state *pending;
if (!b->shutting_down) {
if (!b->compositor->shutting_down) {
pending = drm_pending_state_alloc(device);
drm_output_get_disable_state(pending, output);
drm_pending_state_apply_sync(pending);
......@@ -2796,6 +2796,7 @@ drm_writeback_populate_formats(struct drm_writeback *wb)
drmModePropertyBlobPtr blob;
uint32_t *blob_formats;
unsigned int i;
int ret = 0;
blob_id = drm_property_get_value(&info[WDRM_CONNECTOR_WRITEBACK_PIXEL_FORMATS],
props, 0);
......@@ -2808,16 +2809,17 @@ drm_writeback_populate_formats(struct drm_writeback *wb)
blob_formats = blob->data;
for (i = 0; i < blob->length / sizeof(uint32_t); i++)
for (i = 0; i < blob->length / sizeof(uint32_t); i++) {
if (!weston_drm_format_array_add_format(&wb->formats,
blob_formats[i]))
goto err;
return 0;
blob_formats[i])) {
ret = -1;
break;
}
}
err:
drmModeFreePropertyBlob(blob);
return -1;
return ret;
}
/**
......@@ -3174,8 +3176,6 @@ drm_destroy(struct weston_backend *backend)
wl_event_source_remove(b->udev_drm_source);
wl_event_source_remove(b->drm_source);
b->shutting_down = true;
destroy_sprites(b->drm);
weston_log_scope_destroy(b->debug);
......
......@@ -8638,6 +8638,8 @@ weston_compositor_shutdown(struct weston_compositor *ec)
{
struct weston_output *output, *next;
ec->shutting_down = true;
wl_event_source_remove(ec->idle_source);
wl_event_source_remove(ec->repaint_timer);
......
......@@ -136,8 +136,8 @@ if dep_xkbcommon.version().version_compare('>= 0.5.0')
config_h.set('HAVE_XKBCOMMON_COMPOSE', '1')
endif
dep_wayland_server = dependency('wayland-server', version: '>= 1.20.0')
dep_wayland_client = dependency('wayland-client', version: '>= 1.20.0')
dep_wayland_server = dependency('wayland-server', version: '>= 1.22.0')
dep_wayland_client = dependency('wayland-client', version: '>= 1.22.0')
dep_pixman = dependency('pixman-1', version: '>= 0.25.2')
dep_libinput = dependency('libinput', version: '>= 1.2.0')
dep_libevdev = dependency('libevdev')
......
......@@ -85,7 +85,7 @@ TEST(drm_writeback_screenshot) {
pixman_image_t *diffimg = NULL;
struct wl_surface *surface;
struct rectangle clip;
const char *fname;
char *fname;
bool match;
int frame;
......@@ -113,6 +113,7 @@ TEST(drm_writeback_screenshot) {
screenshot = client_capture_output(client, client->output,
WESTON_CAPTURE_V1_SOURCE_WRITEBACK);
assert(screenshot);
buffer_destroy(screenshot);
/* take another screenshot; this is important to ensure the
* writeback state machine is working correctly */
......@@ -126,6 +127,7 @@ TEST(drm_writeback_screenshot) {
testlog("Loading good reference image %s\n", fname);
reference = load_image_from_png(fname);
assert(reference);
free(fname);
/* check if they match - only the colored square matters, so the
* clip is used to ignore the background */
......@@ -140,11 +142,13 @@ TEST(drm_writeback_screenshot) {
fname = screenshot_output_filename("drm-writeback-screenshot-error", 0);
write_image_as_png(diffimg, fname);
pixman_image_unref(diffimg);
free(fname);
}
pixman_image_unref(reference);
buffer_destroy(screenshot);
buffer_destroy(buffer);
client_destroy(client);
assert(match);
}
\ No newline at end of file
}
......@@ -53,6 +53,8 @@ fixture_setup(struct weston_test_harness *harness)
{
struct compositor_setup setup;
unsetenv("DISPLAY");
compositor_setup_defaults(&setup);
setup.shell = SHELL_TEST_DESKTOP;
setup.xwayland = true;
......@@ -122,6 +124,8 @@ TEST(xwayland_client_test)
color_rgb888(&bg_color, 255, 0, 0);
assert(getenv("DISPLAY"));
conn = create_x11_connection();
assert(conn);
window = create_x11_window(100, 100, 100, 100, conn, bg_color, NULL);
......
......@@ -41,6 +41,15 @@
#include "shared/helpers.h"
#include "shared/string-helpers.h"
static void
weston_xserver_client_destroyed(struct wl_listener *listener, void *data)
{
struct weston_xserver *wxs =
container_of(listener, struct weston_xserver, client_destroy_listener);
wxs->client = NULL;
}
static int
weston_xserver_handle_event(int listen_fd, uint32_t mask, void *data)
{
......@@ -49,13 +58,15 @@ weston_xserver_handle_event(int listen_fd, uint32_t mask, void *data)
snprintf(display, sizeof display, ":%d", wxs->display);
wxs->pid = wxs->spawn_func(wxs->user_data, display, wxs->abstract_fd, wxs->unix_fd);
if (wxs->pid == -1) {
wxs->client = wxs->spawn_func(wxs->user_data, display, wxs->abstract_fd, wxs->unix_fd);
if (wxs->client == NULL) {
weston_log("Failed to spawn the Xwayland server\n");
return 1;
}
wxs->client_destroy_listener.notify = weston_xserver_client_destroyed;
wl_client_add_destroy_late_listener(wxs->client,
&wxs->client_destroy_listener);
weston_log("Spawned Xwayland server, pid %d\n", wxs->pid);
wl_event_source_remove(wxs->abstract_source);
wl_event_source_remove(wxs->unix_source);
......@@ -71,7 +82,10 @@ weston_xserver_shutdown(struct weston_xserver *wxs)
unlink(path);
snprintf(path, sizeof path, "/tmp/.X11-unix/X%d", wxs->display);
unlink(path);
if (wxs->pid == 0) {
if (wxs->client) {
wl_client_destroy(wxs->client);
wxs->client = NULL;
} else {
wl_event_source_remove(wxs->abstract_source);
wl_event_source_remove(wxs->unix_source);
}
......@@ -222,9 +236,9 @@ static void
weston_xserver_destroy(struct wl_listener *l, void *data)
{
struct weston_xserver *wxs =
container_of(l, struct weston_xserver, destroy_listener);
container_of(l, struct weston_xserver, compositor_destroy_listener);
wl_list_remove(&wxs->destroy_listener.link);
wl_list_remove(&wxs->compositor_destroy_listener.link);
if (wxs->loop)
weston_xserver_shutdown(wxs);
......@@ -245,7 +259,7 @@ weston_xwayland_get(struct weston_compositor *compositor)
if (!listener)
return NULL;
wxs = wl_container_of(listener, wxs, destroy_listener);
wxs = wl_container_of(listener, wxs, compositor_destroy_listener);
return (struct weston_xwayland *)wxs;
}
......@@ -305,21 +319,19 @@ retry:
}
static void
weston_xwayland_xserver_loaded(struct weston_xwayland *xwayland,
struct wl_client *client, int wm_fd)
weston_xwayland_xserver_loaded(struct weston_xwayland *xwayland, int wm_fd)
{
struct weston_xserver *wxs = (struct weston_xserver *)xwayland;
wxs->wm = weston_wm_create(wxs, wm_fd);
wxs->client = client;
}
static void
weston_xwayland_xserver_exited(struct weston_xwayland *xwayland,
int exit_status)
weston_xwayland_xserver_exited(struct weston_xwayland *xwayland)
{
struct weston_xserver *wxs = (struct weston_xserver *)xwayland;
wxs->pid = 0;
if (wxs->client)
wl_client_destroy(wxs->client);
wxs->client = NULL;
wxs->abstract_source =
......@@ -332,14 +344,14 @@ weston_xwayland_xserver_exited(struct weston_xwayland *xwayland,
weston_xserver_handle_event, wxs);
if (wxs->wm) {
weston_log("xserver exited, code %d\n", exit_status);
weston_log("xserver exited, will restart on demand\n");
weston_wm_destroy(wxs->wm);
wxs->wm = NULL;
} else {
/* If the X server crashes before it binds to the
* xserver interface, shut down and don't try
* again. */
weston_log("xserver crashing too fast: %d\n", exit_status);
weston_log("xserver crashing too fast, not restarting\n");
weston_xserver_shutdown(wxs);
}
}
......@@ -367,7 +379,7 @@ weston_module_init(struct weston_compositor *compositor)
wxs->compositor = compositor;
if (!weston_compositor_add_destroy_listener_once(compositor,
&wxs->destroy_listener,
&wxs->compositor_destroy_listener,
weston_xserver_destroy)) {
free(wxs);
return 0;
......@@ -402,7 +414,7 @@ weston_module_init(struct weston_compositor *compositor)
return 0;
out_free:
wl_list_remove(&wxs->destroy_listener.link);
wl_list_remove(&wxs->compositor_destroy_listener.link);
free(wxs);
return -1;
}