...
 
Commits (34)
......@@ -30,6 +30,11 @@ following set of shell commands:
/usr/bin/weston-terminal
kill %1
It's possible to set up the local and remote processes so that, when the
connection between the the sockets used by each end breaks, one can create
a new forwarded socket on the remote side and reconnect the two processes.
For a more detailed example, see the man page.
## Installing
Build with meson[0]. A typical incantation is
......@@ -49,24 +54,27 @@ Requirements:
* libgbm (optional, to support programs using OpenGL via DMABUFs)
* libdrm (optional, same as for libgbm)
* ffmpeg (optional, >=3.1, needs avcodec/avutil/swscale for lossy video encoding)
* libva (optional, for hardware video encoding and decoding)
* scdoc (optional, to generate a man page)
* sys/sdt.h (optional, to provide static tracepoints for profiling)
* ssh (runtime, OpenSSH >= 6.7, for Unix domain socket forwarding)
* libx264 (ffmpeg runtime, for software video decoding and encoding)
[0] [https://mesonbuild.com/](https://mesonbuild.com/)
[1] [https://git.sr.ht/~sircmpwn/scdoc](https://git.sr.ht/~sircmpwn/scdoc)
## Status
This is just a prototype right now[0]. The main development location[1],
command-line interface, and project name may yet change completely. Bug
reports and patches are always welcome.
This is usable, but very unstable right now[0]. The main development
location[1], command-line interface, wire format, and project name may
yet change completely. Bug reports and patches are always welcome.
Any of the following will crash waypipe:
* Different local/client and remote/server versions
* Applications using unexpected protocols that pass file descriptors
* Differing byte orders
* Applications using unexpected protocols that pass file descriptors; file
bug reports for these
[0] [https://mstoeckl.com/notes/gsoc/blog.html](https://mstoeckl.com/notes/gsoc/blog.html)
[1] [https://gitlab.freedesktop.org/mstoeckl/waypipe/](https://gitlab.freedesktop.org/mstoeckl/waypipe/)
This diff is collapsed.
......@@ -36,7 +36,7 @@ int init_render_data(struct render_data *data)
}
void cleanup_render_data(struct render_data *data) { (void)data; }
struct gbm_bo *import_dmabuf(struct render_data *rd, int fd, size_t *size,
struct dmabuf_slice_data *info)
const struct dmabuf_slice_data *info)
{
(void)rd;
(void)fd;
......@@ -57,11 +57,10 @@ int get_unique_dmabuf_handle(
(void)temporary_bo;
return -1;
}
struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
size_t size, struct dmabuf_slice_data *info)
struct gbm_bo *make_dmabuf(struct render_data *rd, size_t size,
const struct dmabuf_slice_data *info)
{
(void)rd;
(void)data;
(void)size;
(void)info;
return NULL;
......@@ -130,7 +129,7 @@ int init_render_data(struct render_data *data)
int drm_fd = open(card, O_RDWR | O_CLOEXEC);
if (drm_fd == -1) {
wp_log(WP_ERROR, "Failed to open drm fd for %s: %s", card,
wp_error("Failed to open drm fd for %s: %s", card,
strerror(errno));
data->disabled = true;
return -1;
......@@ -140,7 +139,7 @@ int init_render_data(struct render_data *data)
if (!dev) {
data->disabled = true;
close(drm_fd);
wp_log(WP_ERROR, "Failed to create gbm device from drm_fd");
wp_error("Failed to create gbm device from drm_fd");
return -1;
}
......@@ -158,19 +157,19 @@ void cleanup_render_data(struct render_data *data)
data->dev = NULL;
data->drm_fd = -1;
}
cleanup_hwcontext(data);
}
static long get_dmabuf_fd_size(int fd)
{
ssize_t endp = lseek(fd, 0, SEEK_END);
if (endp == -1) {
wp_log(WP_ERROR,
"Failed to estimate dmabuf size with lseek: %s",
wp_error("Failed to estimate dmabuf size with lseek: %s",
strerror(errno));
return -1;
}
if (lseek(fd, 0, SEEK_SET) == -1) {
wp_log(WP_ERROR, "Failed to reset dmabuf offset with lseek: %s",
wp_error("Failed to reset dmabuf offset with lseek: %s",
strerror(errno));
return -1;
}
......@@ -178,7 +177,7 @@ static long get_dmabuf_fd_size(int fd)
}
struct gbm_bo *import_dmabuf(struct render_data *rd, int fd, size_t *size,
struct dmabuf_slice_data *info)
const struct dmabuf_slice_data *info)
{
ssize_t endp = get_dmabuf_fd_size(fd);
if (endp == -1) {
......@@ -194,7 +193,8 @@ struct gbm_bo *import_dmabuf(struct render_data *rd, int fd, size_t *size,
// fd
data.modifier = info->modifier;
data.num_fds = 0;
for (unsigned int i = 0; i < info->num_planes; i++) {
uint32_t simple_format = 0;
for (int i = 0; i < info->num_planes; i++) {
if (info->using_planes[i]) {
data.fds[data.num_fds] = fd;
data.strides[data.num_fds] =
......@@ -202,11 +202,18 @@ struct gbm_bo *import_dmabuf(struct render_data *rd, int fd, size_t *size,
data.offsets[data.num_fds] =
(int)info->offsets[i];
data.num_fds++;
if (!simple_format) {
simple_format = dmabuf_get_simple_format_for_plane(
info->format, i);
}
}
}
if (!simple_format) {
simple_format = info->format;
}
data.width = info->width;
data.height = info->height;
data.format = info->format;
data.format = simple_format;
} else {
data.num_fds = 1;
data.fds[0] = fd;
......@@ -221,7 +228,7 @@ struct gbm_bo *import_dmabuf(struct render_data *rd, int fd, size_t *size,
struct gbm_bo *bo = gbm_bo_import(rd->dev, GBM_BO_IMPORT_FD_MODIFIER,
&data, GBM_BO_USE_RENDERING);
if (!bo) {
wp_log(WP_ERROR, "Failed to import dmabuf to gbm bo: %s",
wp_error("Failed to import dmabuf to gbm bo: %s",
strerror(errno));
return NULL;
}
......@@ -235,8 +242,7 @@ bool is_dmabuf(int fd)
struct dma_buf_sync sync;
sync.flags = 0;
if (ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync) != -1) {
wp_log(WP_ERROR,
"DMAbuf test ioctl succeeded when it should have errored");
wp_error("DMAbuf test ioctl succeeded when it should have errored");
return false;
}
if (errno == EINVAL) {
......@@ -244,8 +250,7 @@ bool is_dmabuf(int fd)
} else if (errno == ENOTTY) {
return false;
} else {
wp_log(WP_ERROR,
"Unexpected error from dmabuf detection probe: %d, %s",
wp_error("Unexpected error from dmabuf detection probe: %d, %s",
errno, strerror(errno));
return false;
}
......@@ -271,8 +276,8 @@ int get_unique_dmabuf_handle(
return handle;
}
struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
size_t size, struct dmabuf_slice_data *info)
struct gbm_bo *make_dmabuf(struct render_data *rd, size_t size,
const struct dmabuf_slice_data *info)
{
struct gbm_bo *bo;
if (!info || info->num_planes == 0) {
......@@ -284,14 +289,13 @@ struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
bo = gbm_bo_create(rd->dev, width, height, format,
GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING);
if (!bo) {
wp_log(WP_ERROR, "Failed to make dmabuf: %s",
strerror(errno));
wp_error("Failed to make dmabuf: %s", strerror(errno));
return NULL;
}
} else {
uint64_t modifiers[2] = {info->modifier, GBM_BO_USE_RENDERING};
// assuming the format is a very standard one which can be
// created by gbm_bo;
uint32_t simple_format = dmabuf_get_simple_format_for_plane(
info->format, 0);
/* Whether just size and modifiers suffice to replicate
* a surface is driver dependent, and requires actual testing
......@@ -308,10 +312,9 @@ struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
* the size of the buffer contents.
*/
bo = gbm_bo_create_with_modifiers(rd->dev, info->width,
info->height, info->format, modifiers, 2);
info->height, simple_format, modifiers, 2);
if (!bo) {
wp_log(WP_ERROR,
"Failed to make dmabuf (with modifier %lx): %s",
wp_error("Failed to make dmabuf (with modifier %lx): %s",
info->modifier, strerror(errno));
return NULL;
}
......@@ -319,8 +322,7 @@ struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
long csize = get_dmabuf_fd_size(tfd);
close(tfd);
if (csize != (long)size) {
wp_log(WP_ERROR,
"Created DMABUF size (%ld disagrees with original size (%ld), %s",
wp_error("Created DMABUF size (%ld disagrees with original size (%ld), %s",
csize, size,
(csize > (long)size)
? "keeping anyway"
......@@ -336,37 +338,30 @@ struct gbm_bo *make_dmabuf(struct render_data *rd, const char *data,
gbm_bo_destroy(bo);
bo = gbm_bo_create_with_modifiers(rd->dev,
info->width, nheight,
info->format, modifiers, 2);
simple_format, modifiers, 2);
if (!bo) {
wp_error("Failed to make extra-sized dmabuf (with modifier %lx): %s",
info->modifier,
strerror(errno));
return NULL;
}
int nfd = gbm_bo_get_fd(bo);
long nsize = get_dmabuf_fd_size(nfd);
close(nfd);
if (nsize < (long)size) {
wp_log(WP_ERROR,
"Trying to fudge dmabuf height to reach target size of %ld bytes; failed, got %ld",
wp_error("Trying to fudge dmabuf height to reach target size of %ld bytes; failed, got %ld",
size, nsize);
}
}
}
}
void *handle = NULL;
// unfortunately, there is no easy way to estimate the writeable region
void *dst = map_dmabuf(bo, true, &handle);
if (!dst) {
gbm_bo_destroy(bo);
return NULL;
}
memcpy(dst, data, size);
// no error message :-(, even though unmap ~ commit
unmap_dmabuf(bo, handle);
return bo;
}
int export_dmabuf(struct gbm_bo *bo)
{
int fd = gbm_bo_get_fd(bo);
if (fd == -1) {
wp_log(WP_ERROR, "Failed to export dmabuf: %s",
strerror(errno));
wp_error("Failed to export dmabuf: %s", strerror(errno));
}
return fd;
}
......@@ -392,7 +387,7 @@ void *map_dmabuf(struct gbm_bo *bo, bool write, void **map_handle)
&stride, map_handle);
if (!data) {
// errno is useless here
wp_log(WP_ERROR, "Failed to map dmabuf");
wp_error("Failed to map dmabuf");
}
return data;
}
......@@ -430,15 +425,20 @@ static const struct multiplanar_info plane_table[] = {
uint32_t dmabuf_get_simple_format_for_plane(uint32_t format, int plane)
{
const uint32_t by_cpp[] = {0, GBM_FORMAT_R8, GBM_FORMAT_GR88,
GBM_FORMAT_RGB888, GBM_BO_FORMAT_ARGB8888};
for (int i = 0; plane_table[i].format; i++) {
if (plane_table[i].format == format) {
int cpp = plane_table[i].planes[plane].cpp;
const uint32_t by_cpp[] = {0, GBM_FORMAT_R8,
GBM_FORMAT_GR88, GBM_FORMAT_RGB888,
GBM_BO_FORMAT_ARGB8888};
return by_cpp[cpp];
}
}
if (format == GBM_FORMAT_YUYV || format == GBM_FORMAT_YVYU ||
format == GBM_FORMAT_UYVY ||
format == GBM_FORMAT_VYUY ||
format == GBM_FORMAT_AYUV) {
return by_cpp[4];
}
return format;
}
......
This diff is collapsed.
......@@ -30,7 +30,12 @@
#include <string.h>
struct merge_stack_elem {
struct interval *v;
int offset;
int count;
};
struct merge_stack {
struct interval *data;
int size;
int count;
};
......@@ -75,6 +80,7 @@ static int stream_merge(int a_count, const struct interval *__restrict__ a_list,
}
static int fix_merge_stack_property(int size, struct merge_stack_elem *stack,
struct merge_stack *base, struct merge_stack *temp,
int merge_margin, bool force_compact, int *absorbed)
{
while (size > 1) {
......@@ -85,17 +91,24 @@ static int fix_merge_stack_property(int size, struct merge_stack_elem *stack,
return size;
}
/* TODO: optimize memory management */
struct interval *combo = malloc((top.count + nxt.count + 1) *
sizeof(struct interval));
int xs = stream_merge(top.count, top.v, nxt.count, nxt.v, combo,
buf_ensure_size(top.count + nxt.count + 1,
sizeof(struct interval), &temp->size,
(void **)&temp->data);
int xs = stream_merge(top.count, &base->data[top.offset],
nxt.count, &base->data[nxt.offset], temp->data,
merge_margin);
free(top.v);
free(nxt.v);
/* There are more complicated/multi-buffer alternatives with
* fewer memory copies, but this is already <20% of stream
* merge time */
memcpy(&base->data[nxt.offset], temp->data,
(size_t)(xs + 1) * sizeof(struct interval));
base->count = nxt.offset + xs + 1;
stack[size - 1] = (struct merge_stack_elem){
.v = NULL, .count = 0};
.offset = 0, .count = 0};
stack[size - 2] = (struct merge_stack_elem){
.v = combo, .count = xs};
.offset = nxt.offset, .count = xs};
size--;
*absorbed += (top.count + nxt.count - xs);
......@@ -111,33 +124,42 @@ void merge_mergesort(const int old_count, struct interval *old_list,
const int new_count, const struct ext_interval *const new_list,
int *dst_count, struct interval **dst_list, int merge_margin)
{
/* Stack-based mergesort: the buffer at position `i+1` should be <= 1/2
* times the size of the buffer at position `i`; buffers will be merged
/* Stack-based mergesort: the buffer at position `i+1`
* should be <= 1/2 times the size of the buffer at
* position `i`; buffers will be merged
* to maintain this invariant */
// TODO: improve memory management!
struct merge_stack_elem substack[32];
int substack_size = 0;
memset(substack, 0, sizeof(substack));
struct merge_stack base = {.data = NULL, .count = 0, .size = 0};
struct merge_stack temp = {.data = NULL, .count = 0, .size = 0};
if (old_count) {
/* seed the stack with the previous damage interval list */
/* seed the stack with the previous damage
* interval list,
* including trailing terminator */
base.data = old_list;
base.size = old_count + 1;
base.count = old_count + 1;
substack[substack_size++] = (struct merge_stack_elem){
.v = old_list, .count = old_count};
.offset = 0, .count = old_count};
}
int src_count = 0, absorbed = 0;
for (int jn = 0; jn < new_count; jn++) {
struct ext_interval e = new_list[jn];
/* ignore invalid intervals -- also, if e.start is close to
* INT32_MIN, the stream merge breaks */
/* ignore invalid intervals -- also, if e.start
* is close to INT32_MIN, the stream merge
* breaks */
if (e.width <= 0 || e.rep <= 0 || e.start < 0) {
continue;
}
/* To limit CPU time, if it is very likely that an interval
* would be merged anyway, then replace it with its containing
* interval. */
/* To limit CPU time, if it is very likely that
* an interval would be merged anyway, then
* replace it with its containing interval. */
int remaining = src_count - absorbed;
bool force_combine = (absorbed > 10000) ||
bool force_combine = (absorbed > 30000) ||
10 * remaining < src_count;
long end = e.start + e.stride * (long)(e.rep - 1) + e.width;
......@@ -146,15 +168,18 @@ void merge_mergesort(const int old_count, struct interval *old_list,
e.width = INT32_MAX - 1 - e.start;
e.rep = 1;
}
/* Remove internal gaps are smaller than the margin and hence
/* Remove internal gaps are smaller than the
* margin and hence
* would need to be merged away anyway. */
if (e.width > e.stride - merge_margin || force_combine) {
e.width = e.stride * (e.rep - 1) + e.width;
e.rep = 1;
}
struct interval *vec =
malloc((e.rep + 1) * sizeof(struct interval));
buf_ensure_size(base.count + e.rep + 1, sizeof(struct interval),
&base.size, (void **)&base.data);
struct interval *vec = &base.data[base.count];
for (int k = 0; k < e.rep; k++) {
vec[k].start = e.start + k * e.stride;
vec[k].end = vec[k].start + e.width;
......@@ -166,19 +191,23 @@ void merge_mergesort(const int old_count, struct interval *old_list,
src_count += e.rep;
substack[substack_size] = (struct merge_stack_elem){
.v = vec, .count = e.rep};
.offset = base.count, .count = e.rep};
substack_size++;
base.count += e.rep + 1;
/* merge down the stack as far as possible */
substack_size = fix_merge_stack_property(substack_size,
substack, merge_margin, false, &absorbed);
substack, &base, &temp, merge_margin, false,
&absorbed);
}
/* collapse the stack into a final interval */
substack_size = fix_merge_stack_property(
substack_size, substack, merge_margin, true, &absorbed);
fix_merge_stack_property(substack_size, substack, &base, &temp,
merge_margin, true, &absorbed);
free(temp.data);
*dst_list = substack[0].v;
*dst_list = base.data;
*dst_count = substack[0].count;
}
......@@ -215,8 +244,7 @@ int get_damage_area(const struct damage *base)
tca += base->damage[i].end - base->damage[i].start;
}
double cover_fraction = base->acc_damage_stat / (double)tca;
wp_log(WP_DEBUG,
"Damage interval: {%d(%d)} -> [%d, %d) [%d], %f",
wp_debug("Damage interval: {%d(%d)} -> [%d, %d) [%d], %f",
base->ndamage_intvs, base->acc_count, low, high,
tca, cover_fraction);
return tca;
......
This diff is collapsed.
......@@ -8,7 +8,7 @@ project(
'warning_level=3',
'werror=true',
],
version: '0.3.0',
version: '0.4.0',
)
cc = meson.get_compiler('c')
......@@ -17,23 +17,19 @@ cc = meson.get_compiler('c')
version = '"@0@"'.format(meson.project_version())
add_project_arguments('-DWAYPIPE_VERSION=@0@'.format(version), language: 'c')
python3 = import('python').find_installation()
# Make build reproducible if possible
python3 = import('python').find_installation()
prefix_finder = 'import os.path; print(os.path.join(os.path.relpath(\'@0@\', \'@1@\'),\'\'))'
r = run_command(python3, '-c', prefix_finder.format(meson.source_root(), meson.build_root()))
relative_dir = r.stdout().strip()
if cc.has_argument('-fmacro-prefix-map=/prefix/to/hide=')
prefix_finder = 'import os.path; print(os.path.join(os.path.relpath(\'@0@\', \'@1@\'),\'\'))'
r = run_command(python3, '-c', prefix_finder.format(meson.source_root(), meson.build_root()))
relative_dir = r.stdout().strip()
add_project_arguments(
'-fmacro-prefix-map=@0@='.format(relative_dir),
language: 'c',
)
else
length_finder = 'import os.path; print(len(os.path.join(os.path.relpath(\'@0@\', \'@1@\'),\'\')))'
rel_src_dir_length = run_command(python3, '-c',
length_finder.format(meson.source_root(), meson.build_root())).stdout().strip()
add_project_arguments(
'-DWAYPIPE_SRC_DIR_LENGTH=@0@'.format(rel_src_dir_length),
'-DWAYPIPE_REL_SRC_DIR="@0@"'.format(relative_dir),
language: 'c',
)
endif
......@@ -65,6 +61,10 @@ libswscale = dependency('libswscale', required: get_option('with_video'))
if libavcodec.found() and libavutil.found() and libswscale.found()
add_project_arguments('-DHAS_VIDEO=1', language: 'c')
endif
libva = dependency('libva', required: get_option('with_vaapi'))
if libva.found()
add_project_arguments('-DHAS_VAAPI=1', language: 'c')
endif
subdir('protocols')
......@@ -77,6 +77,7 @@ waypipe_dependencies = [
pthreads, # To run expensive computations in parallel
protos, # Wayland protocol data
rt, # For shared memory
libva, # For NV12->RGB conversions
]
waypipe_includes = []
......
......@@ -3,3 +3,4 @@ option('with_video', type : 'feature', value : 'auto', description : 'Link with
option('with_dmabuf', type : 'feature', value : 'auto', description : 'Support DMABUFs, the file descriptors used to exchange data for e.g. OpenGL applications')
option('with_lz4', type : 'feature', value : 'auto', description : 'Support LZ4 as a compression mechanism')
option('with_zstd', type : 'feature', value : 'auto', description : 'Support ZStandard as a compression mechanism')
option('with_vaapi', type : 'feature', value : 'auto', description : 'Link with libva and use VAAPI to perform hardware video output color space conversions on GPU')
......@@ -57,8 +57,7 @@ void listset_insert(struct fd_translation_map *map, struct obj_list *lst,
* elements are never duplicated and make the deletion
* process cause crashes */
if (!lst->objs[i]->is_zombie) {
wp_log(WP_ERROR,
"Replacing object @%u that already exists: old type %s, new type %s",
wp_error("Replacing object @%u that already exists: old type %s, new type %s",
obj->obj_id,
get_type_name(lst->objs[i]),
get_type_name(obj));
......@@ -95,7 +94,7 @@ void listset_remove(struct obj_list *lst, struct wp_object *obj)
}
}
wp_log(WP_ERROR, "Object not in list");
wp_error("Object not in list");
return;
}
struct wp_object *listset_get(struct obj_list *lst, uint32_t id)
......@@ -152,14 +151,14 @@ bool size_check(const struct msg_data *data, const uint32_t *payload,
unsigned int true_length, int fd_length)
{
if (data->n_fds > fd_length) {
wp_log(WP_ERROR, "Msg overflow, not enough fds %d > %d",
data->n_fds, fd_length);
wp_error("Msg overflow, not enough fds %d > %d", data->n_fds,
fd_length);
return false;
}
unsigned int len = data->base_gap;
if (len > true_length) {
wp_log(WP_ERROR, "Msg overflow, not enough words %d > %d", len,
wp_error("Msg overflow, not enough words %d > %d", len,
true_length);
return false;
}
......@@ -174,8 +173,7 @@ bool size_check(const struct msg_data *data, const uint32_t *payload,
if (end_idx < true_length &&
!word_has_empty_bytes(
payload[end_idx])) {
wp_log(WP_ERROR,
"Msg overflow, string termination %d < %d, %d, %x %d",
wp_error("Msg overflow, string termination %d < %d, %d, %x %d",
len, true_length, x_words,
payload[end_idx],
word_has_empty_bytes(
......@@ -186,8 +184,8 @@ bool size_check(const struct msg_data *data, const uint32_t *payload,
len += x_words;
len += data->trail_gap[i];
if (len > true_length) {
wp_log(WP_ERROR, "Msg overflow, post string %d %d > %d",
i, len, true_length);
wp_error("Msg overflow, post string %d %d > %d", i, len,
true_length);
return false;
}
}
......@@ -215,8 +213,7 @@ static bool build_new_objects(const struct msg_data *data,
} else {
uint32_t new_id = payload[pos + data->new_obj_idxs[k]];
if (new_id == caller_obj->obj_id) {
wp_log(WP_ERROR,
"In %s.%s, tried to create object id=%u conflicting with object being called, also id=%u",
wp_error("In %s.%s, tried to create object id=%u conflicting with object being called, also id=%u",
caller_obj->type->name,
data->name, new_id,
caller_obj->obj_id);
......@@ -245,7 +242,7 @@ enum parse_state handle_message(struct globals *g, bool display_side,
int meth = (int)((header[1] << 16) >> 16);
int len = (int)(header[1] >> 16);
if (len != chars->zone_end - chars->zone_start) {
wp_log(WP_ERROR, "Message length disagreement %d vs %d", len,
wp_error("Message length disagreement %d vs %d", len,
chars->zone_end - chars->zone_start);
return PARSE_ERROR;
}
......@@ -253,7 +250,7 @@ enum parse_state handle_message(struct globals *g, bool display_side,
struct wp_object *objh = listset_get(&g->tracker.objects, obj);
if (!objh || !objh->type) {
wp_log(WP_DEBUG, "Unidentified object %d with %s", obj,
wp_debug("Unidentified object %d with %s", obj,
from_client ? "request" : "event");
return PARSE_UNKNOWN;
}
......@@ -264,12 +261,11 @@ enum parse_state handle_message(struct globals *g, bool display_side,
if (meth < intf->nfuncs[type_idx] && meth >= 0) {
msg = &intf->funcs[type_idx][meth];
} else {
wp_log(WP_DEBUG,
"Unidentified request #%d (of %d) on interface %s",
wp_debug("Unidentified request #%d (of %d) on interface %s",
meth, intf->nfuncs[type_idx], intf->name);
}
if (!msg) {
wp_log(WP_DEBUG, "Unidentified %s from known object",
wp_debug("Unidentified %s from known object",
from_client ? "request" : "event");
return PARSE_UNKNOWN;
}
......@@ -288,8 +284,8 @@ enum parse_state handle_message(struct globals *g, bool display_side,
const uint32_t *payload = header + 2;
if (!size_check(msg, payload, len / 4 - 2,
fds->zone_end - fds->zone_start)) {
wp_log(WP_ERROR, "Message %x %s@%u.%s parse length overflow",
payload, intf->name, objh->obj_id, msg->name);
wp_error("Message %x %s@%u.%s parse length overflow", payload,
intf->name, objh->obj_id, msg->name);
return PARSE_UNKNOWN;
}
......@@ -344,8 +340,8 @@ enum parse_state handle_message(struct globals *g, bool display_side,
}
if (ctx.drop_this_msg) {
wp_log(WP_DEBUG, "Dropping %s.%s, with %d fds", intf->name,
msg->name, fds_used);
wp_debug("Dropping %s.%s, with %d fds", intf->name, msg->name,
fds_used);
chars->zone_end = chars->zone_start;
int nmoved = fds->zone_end - fds->zone_start - fds_used;
memmove(&fds->data[fds->zone_start],
......@@ -360,8 +356,7 @@ enum parse_state handle_message(struct globals *g, bool display_side,
fds->zone_start += fds_used;
}
if (fds->zone_end < fds->zone_start) {
wp_log(WP_ERROR,
"Handler error after %s.%s: fdzs = %d > %d = fdze",
wp_error("Handler error after %s.%s: fdzs = %d > %d = fdze",
intf->name, msg->name, fds->zone_start,
fds->zone_end);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -70,8 +70,6 @@ int main(int argc, char **argv)
bool all_success = true;
struct damage d = {NULL, 0, 0, 0};
damage_everything(&d);
int nsubtests = (sizeof(subtests) / sizeof(subtests[0]));
for (int i = 0; i < nsubtests; i++) {
struct subtest test = subtests[i];
......@@ -84,17 +82,25 @@ int main(int argc, char **argv)
uint64_t ns01 = 0, ns12 = 0;
long nruns = 0;
size_t net_diffsize = 0;
for (int x = 0; x < test.repetitions; x++) {
nruns += rand_gap_fill(source, test.size, test.max_gap);
net_diffsize = 0;
for (int s = 0; s < test.shards; s++) {
// TODO: manage sharding and boundary
struct interval damage;
damage.start = (s * (int)test.size) /
test.shards;
damage.end = ((s + 1) * (int)test.size) /
test.shards;
size_t diffsize = 0;
struct timespec t0, t1, t2;
clock_gettime(CLOCK_MONOTONIC, &t0);
construct_diff(test.size, &d, s, test.shards,
mirror, source, &diffsize,
diff);
construct_diff(test.size, &damage, 1, mirror,
source, &diffsize, diff);
clock_gettime(CLOCK_MONOTONIC, &t1);
apply_diff(test.size, target1, target2,
diffsize, diff);
......
This diff is collapsed.
......@@ -44,6 +44,7 @@
struct copy_setup {
int conn;
int wayl;
int link;
bool is_display_side;
struct main_config *mc;
};
......@@ -51,7 +52,7 @@ struct copy_setup {
void *start_looper(void *data)
{
struct copy_setup *setup = (struct copy_setup *)data;
main_interface_loop(setup->conn, setup->wayl, setup->mc,
main_interface_loop(setup->conn, setup->wayl, setup->link, setup->mc,
setup->is_display_side);
return NULL;
}
......@@ -72,7 +73,7 @@ static void atomic_logger(const char *file, int line, enum log_level level,
msg[nwri++] = '\n';
msg[nwri] = 0;
write(STDOUT_FILENO, msg, (size_t)nwri);
(void)write(STDOUT_FILENO, msg, (size_t)nwri);
(void)level;
}
......@@ -103,14 +104,18 @@ int main(int argc, char **argv)
}
lseek(fd, 0, SEEK_SET);
char *buf = malloc(len);
read(fd, buf, len);
if (read(fd, buf, len) == -1) {
return EXIT_FAILURE;
}
close(fd);
printf("Loaded %ld bytes\n", len);
int srv_fds[2], cli_fds[2], conn_fds[2];
int srv_fds[2], cli_fds[2], conn_fds[2], srv_links[2], cli_links[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, srv_fds) == -1 ||
socketpair(AF_UNIX, SOCK_STREAM, 0, cli_fds) == -1 ||
socketpair(AF_UNIX, SOCK_STREAM, 0, conn_fds) == -1) {
socketpair(AF_UNIX, SOCK_STREAM, 0, conn_fds) == -1 ||
socketpair(AF_UNIX, SOCK_STREAM, 0, srv_links) == -1 ||
socketpair(AF_UNIX, SOCK_STREAM, 0, cli_links) == -1) {
printf("Socketpair failed\n");
return EXIT_FAILURE;
}
......@@ -126,10 +131,12 @@ int main(int argc, char **argv)
pthread_t thread_a, thread_b;
struct copy_setup server_conf = {.conn = conn_fds[0],
.wayl = srv_fds[1],
.link = srv_links[1],
.is_display_side = true,
.mc = &config};
struct copy_setup client_conf = {.conn = conn_fds[1],
.wayl = cli_fds[1],
.link = cli_links[1],
.is_display_side = false,
.mc = &config};
if (pthread_create(&thread_a, NULL, start_looper, &server_conf) == -1) {
......@@ -158,8 +165,7 @@ int main(int argc, char **argv)
/* 'copy' sink */
new_fileno = open("/dev/null", O_WRONLY);
if (new_fileno == -1) {
wp_log(WP_ERROR,
"Failed to open /dev/null");
wp_error("Failed to open /dev/null");
}
} else {
/* avoid buffer overflow */
......@@ -177,10 +183,9 @@ int main(int argc, char **argv)
unlink(template);
#endif
if (new_fileno == -1) {
wp_log(WP_ERROR, "Failed to mkstemp");
wp_error("Failed to mkstemp");
} else if (ftruncate(new_fileno, fsize) == -1) {
wp_log(WP_ERROR,
"Failed to resize tempfile");
wp_error("Failed to resize tempfile");
close(new_fileno);
new_fileno = -1;
}
......@@ -252,12 +257,11 @@ int main(int argc, char **argv)
int target_fd = to_server ? srv_fds[0] : cli_fds[0];
ssize_t ret = sendmsg(target_fd, &msg, 0);
if (ret == -1) {
wp_log(WP_ERROR, "Error in sendmsg");
wp_error("Error in sendmsg");
break;
}
} else {
wp_log(WP_ERROR,
"Failed to send message before timeout");
wp_error("Failed to send message before timeout");
}
if (new_fileno != -1) {
close(new_fileno);
......@@ -280,8 +284,7 @@ int main(int argc, char **argv)
printf("Poll error\n");
break;
} else if (nr == 0) {
wp_log(WP_DEBUG, "No reply to sent packet %d",
packet_size);
wp_debug("No reply to sent packet %d", packet_size);
}
for (int i = 0; i < 2; i++) {
if (read_pfds[i].revents & POLLIN) {
......@@ -299,7 +302,7 @@ int main(int argc, char **argv)
msg.msg_flags = 0;
ssize_t ret = recvmsg(read_pfds[i].fd, &msg, 0);
if (ret == -1) {
wp_log(WP_ERROR, "Error in recvmsg");
wp_error("Error in recvmsg");
}
}
}
......@@ -312,6 +315,9 @@ int main(int argc, char **argv)
pthread_join(thread_a, NULL);
pthread_join(thread_b, NULL);
close(srv_links[0]);
close(cli_links[0]);
free(buf);
free(ignore_buf);
return EXIT_SUCCESS;
......
......@@ -28,7 +28,7 @@ def safe_cleanup(process):
if process.poll() is None:
# certain weston client programs appear to initiate shutdown proceedings correctly; however, they appear to wait for a frame beforehand, and the headless weston doesn't ask for additional frames
process.send_signal(signal.SIGINT)
time.sleep(0.01)
time.sleep(0.1)
try:
process.wait(100)
except subprocess.TimeoutExpired:
......
......@@ -110,7 +110,7 @@ int main(int argc, char **argv)
destroy_wp_object(NULL, old_display);
struct fd_translation_map map;
setup_translation_map(&map, false, COMP_NONE, 1);
setup_translation_map(&map, false);
struct wp_object xobj;
xobj.type = &intf_xtype;
......@@ -178,8 +178,7 @@ int main(int argc, char **argv)
bool sp = size_check(wt->data, wt->words,
length, fdlen);
if (sp != expect_success) {
wp_log(WP_ERROR,
"size check FAIL (%c, expected %c) at %d/%d chars, %d/%d fds",
wp_error("size check FAIL (%c, expected %c) at %d/%d chars, %d/%d fds",
sp ? 'Y' : 'n',
expect_success ? 'Y'
: 'n',
......
......@@ -76,34 +76,33 @@ int setup_nb_socket(const char *socket_path, int nmaxclients)
int sock;
if (strlen(socket_path) >= sizeof(saddr.sun_path)) {
wp_log(WP_ERROR,
"Socket path is too long and would be truncated: %s",
wp_error("Socket path is too long and would be truncated: %s",
socket_path);
return -1;
}
saddr.sun_family = AF_UNIX;
strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path) - 1);
sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
wp_log(WP_ERROR, "Error creating socket: %s", strerror(errno));
wp_error("Error creating socket: %s", strerror(errno));
return -1;
}
if (set_nonblocking(sock) == -1) {
wp_log(WP_ERROR, "Error making socket nonblocking: %s",
wp_error("Error making socket nonblocking: %s",
strerror(errno));
close(sock);
return -1;
}
if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
wp_log(WP_ERROR, "Error binding socket at %s: %s", socket_path,
wp_error("Error binding socket at %s: %s", socket_path,
strerror(errno));
close(sock);
return -1;
}
if (listen(sock, nmaxclients) == -1) {
wp_log(WP_ERROR, "Error listening to socket at %s: %s",
socket_path, strerror(errno));
wp_error("Error listening to socket at %s: %s", socket_path,
strerror(errno));
close(sock);
unlink(socket_path);
return -1;
......@@ -118,7 +117,7 @@ int connect_to_socket(const char *socket_path)
saddr.sun_family = AF_UNIX;
int len = (int)strlen(socket_path);
if (len >= (int)sizeof(saddr.sun_path)) {
wp_log(WP_ERROR, "Socket path (%s) is too long, at %d bytes",
wp_error("Socket path (%s) is too long, at %d bytes",
socket_path, len);
return -1;
}
......@@ -126,19 +125,48 @@ int connect_to_socket(const char *socket_path)
chanfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (chanfd == -1) {
wp_log(WP_ERROR, "Error creating socket: %s", strerror(errno));
wp_error("Error creating socket: %s", strerror(errno));
return -1;
}
if (connect(chanfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) {
wp_log(WP_ERROR, "Error connecting to socket (%s): %s",
socket_path, strerror(errno));
wp_error("Error connecting to socket (%s): %s", socket_path,
strerror(errno));
close(chanfd);
return -1;
}
return chanfd;
}
int send_one_fd(int socket, int fd)
{
union {
char buf[CMSG_SPACE(sizeof(int))];
struct cmsghdr align;
} uc;
memset(uc.buf, 0, sizeof(uc.buf));
struct cmsghdr *frst = (struct cmsghdr *)(uc.buf);
frst->cmsg_level = SOL_SOCKET;
frst->cmsg_type = SCM_RIGHTS;
*((int *)CMSG_DATA(frst)) = fd;
frst->cmsg_len = CMSG_LEN(sizeof(int));
struct iovec the_iovec;
the_iovec.iov_len = 1;
uint8_t dummy_data = 1;
the_iovec.iov_base = &dummy_data;
struct msghdr msg;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &the_iovec;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = uc.buf;
msg.msg_controllen = CMSG_SPACE(sizeof(int));
return (int)sendmsg(socket, &msg, 0);
}
void test_log_handler(const char *file, int line, enum log_level level,
const char *fmt, ...)
{
......@@ -151,29 +179,43 @@ void test_log_handler(const char *file, int line, enum log_level level,
printf("\n");
}
bool wait_for_pid_and_clean(pid_t target_pid, int *status, int options)
bool wait_for_pid_and_clean(pid_t target_pid, int *status, int options,
struct conn_map *map)
{
bool found = false;
while (1) {
int stat;
pid_t r = waitpid((pid_t)-1, &stat, options);
if (r > 0) {
wp_log(WP_DEBUG, "Child process %d has died", r);
if (r == target_pid) {
target_pid = 0;
*status = stat;
found = true;
}
continue;
}
if (r == -1 && (errno == ECHILD || errno == EINTR)) {
if (r == 0 || (r == -1 && (errno == ECHILD ||
errno == EINTR))) {
// Valid exit reasons, not an error
errno = 0;
return found;
} else if (r == -1) {
wp_log(WP_ERROR, "waitpid failed: %s", strerror(errno));
wp_error("waitpid failed: %s", strerror(errno));
return found;
}
wp_debug("Child process %d has died", r);
if (map) {
/* Clean out all entries matching that pid */
int iw = 0;
for (int ir = 0; ir < map->count; ir++) {
map->data[iw] = map->data[ir];
if (map->data[ir].pid != r) {
iw++;
} else {
close(map->data[ir].linkfd);
}
}
map->count = iw;
}
if (r == target_pid) {
target_pid = 0;
*status = stat;
found = true;
}
return found;
}
}
......@@ -185,6 +227,9 @@ int buf_ensure_size(int count, size_t obj_size, int *space, void **data)
if (count >= INT32_MAX / 2 || count <= 0) {
return -1;
}
if (*space < 1) {
*space = 1;
}
while (*space < count) {
*space *= 2;
}
......@@ -195,3 +240,64 @@ int buf_ensure_size(int count, size_t obj_size, int *space, void **data)
}
return -1;
}
static const char *wmsg_types[] = {
"WMSG_PROTOCOL",
"WMSG_INJECT_RIDS",
"WMSG_OPEN_FILE",
"WMSG_EXTEND_FILE",
"WMSG_OPEN_DMABUF",
"WMSG_BUFFER_FILL",
"WMSG_BUFFER_DIFF",
"WMSG_OPEN_IR_PIPE",
"WMSG_OPEN_IW_PIPE",
"WMSG_OPEN_RW_PIPE",
"WMSG_PIPE_TRANSFER",
"WMSG_PIPE_HANGUP",
"WMSG_OPEN_DMAVID_SRC",
"WMSG_OPEN_DMAVID_DST",
"WMSG_SEND_DMAVID_PACKET",
"WMSG_ACK_NBLOCKS",
};
const char *wmsg_type_to_str(enum wmsg_type tp)
{
if (tp >= sizeof(wmsg_types) / sizeof(wmsg_types[0])) {
return "???";
}
return wmsg_types[tp];
}
bool transfer_add(struct transfer_data *transfers, size_t size, void *data,
uint32_t msgno)
{
if (pthread_mutex_trylock(&transfers->lock) == 0) {
wp_error("Transfer operation happening without lock");
pthread_mutex_unlock(&transfers->lock);
}
if (size == 0) {
return true;
}
int sz2 = transfers->size;
if (buf_ensure_size(transfers->end + 1, sizeof(*transfers->data),
&transfers->size,
(void **)&transfers->data) == -1) {
wp_error("Resize of transfer data failed");
return false;
}
if (buf_ensure_size(transfers->end + 1, sizeof(*transfers->msgno), &sz2,
(void **)&transfers->msgno) == -1) {
wp_error("Resize of transfer data failed");
return false;
}
transfers->data[transfers->end].iov_len = size;
transfers->data[transfers->end].iov_base = data;
transfers->msgno[transfers->end] = msgno;
transfers->end++;
return true;
}
bool transfer_zeropad(
struct transfer_data *transfers, size_t size, uint32_t msgno)
{
return transfer_add(transfers, size, transfers->zeros, msgno);
}
This diff is collapsed.
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include "util.h"
#include <fcntl.h>
#include <getopt.h>
#include <signal.h>
#include <stdarg.h>
......@@ -40,13 +41,13 @@
#include <unistd.h>
int run_server(const char *socket_path, const char *display_path,
const struct main_config *config, bool oneshot,
bool unlink_at_end, const char *application,
const char *control_path, const struct main_config *config,
bool oneshot, bool unlink_at_end, const char *application,
char *const app_argv[]);
int run_client(const char *socket_path, const struct main_config *config,
bool oneshot, bool via_socket, pid_t eol_pid);
enum waypipe_mode { MODE_FAIL, MODE_SSH, MODE_CLIENT, MODE_SERVER };
enum waypipe_mode { MODE_FAIL, MODE_SSH, MODE_CLIENT, MODE_SERVER, MODE_RECON };
static bool log_to_tty = false;
static enum waypipe_mode log_mode = MODE_FAIL;
......@@ -66,6 +67,8 @@ static const char usage_string[] =
" a socket to a matching 'waypipe client' instance.\n"
" client Run locally to create a Unix socket to which 'waypipe server'\n"
" instances can connect.\n"
" recon C T Reconnect a 'waypipe server' instance. Writes the new Unix\n"
" socket path T to the control pipe C.\n"
"\n"
"Options:\n"
" -c, --compress C select compression method from: lz4, zstd, none\n"
......@@ -76,16 +79,18 @@ static const char usage_string[] =
" -s, --socket S set the socket path to either create or connect to:\n"
" server default: /tmp/waypipe-server.sock\n"
" client default: /tmp/waypipe-client.sock\n"
" ssh mode: sets the prefix for the socket path\n"
" ssh: sets the prefix for the socket path\n"
" -v, --version print waypipe version and exit\n"
" --display D server,ssh mode: set the Wayland display name or path\n"
" --control C server,ssh: set control pipe to reconnect server\n\n"
" --display D server,ssh: the Wayland display name or path\n"
" --drm-node R set the local render node. default: /dev/dri/renderD128\n"
" --remote-node R ssh mode: set the remote render node path\n"
" --remote-node R ssh: set the remote render node path\n"
" --linear-dmabuf only permit gpu buffers without modifier flags\n"
" --login-shell server mode: if server CMD is empty, run a login shell\n"
" --login-shell server: if server CMD is empty, run a login shell\n"
" --threads T set thread pool size, default=hardware threads/2\n"
" --unlink-socket server mode: unlink the socket that waypipe connects to\n"
" --unlink-socket server: unlink the socket that waypipe connects to\n"
" --video compress certain linear dmabufs only with a video codec\n"
" --hwvideo use --video, and try hardware enc/decoding if available\n"
"\n";
static int usage(int retcode)
......@@ -153,7 +158,7 @@ static void log_handler(const char *file, int line, enum log_level level,
msg[nwri] = 0;
// single short writes are atomic for pipes, at least
write(STDERR_FILENO, msg, (size_t)nwri);
(void)write(STDERR_FILENO, msg, (size_t)nwri);
}
/* produces a random token with a low accidental collision probability */
......@@ -250,6 +255,33 @@ static void setup_login_shell_command(char shell[static 256],
}
}
/* Send the socket at 'recon_path' to the control socket at 'control_path'.
* Because connections are made by address, the waypipe server root process
* must be able to connect to the `recon path`. */
static int run_recon(const char *control_path, const char *recon_path)
{
size_t len = strlen(recon_path);
if (len >= 108) {
fprintf(stderr, "Reconnection socket path \"%s\" too long, %d>=%d\n",
control_path, (int)len, 108);
return EXIT_FAILURE;
}
int cfd = open(control_path, O_WRONLY);
if (cfd == -1) {
fprintf(stderr, "Failed to open control pipe at \"%s\"\n",
control_path);
return EXIT_FAILURE;
}
ssize_t written = write(cfd, recon_path, len + 1);
if ((size_t)written != len + 1) {
close(cfd);
fprintf(stderr, "Failed to write to control pipe\n");
return EXIT_FAILURE;
}
close(cfd);
return EXIT_SUCCESS;
}
void handle_noop(int sig) { (void)sig; }
#define ARG_DISPLAY 1001
......@@ -260,6 +292,8 @@ void handle_noop(int sig) { (void)sig; }
#define ARG_THREADS 1006
#define ARG_UNLINK 1007
#define ARG_VIDEO 1008
#define ARG_HWVIDEO 1009
#define ARG_CONTROL 1010
static const struct option options[] = {
{"compress", required_argument, NULL, 'c'},
......@@ -275,8 +309,10 @@ static const struct option options[] = {
{"login-shell", no_argument, NULL, ARG_LOGIN_SHELL},
{"linear-dmabuf", no_argument, NULL, ARG_LINEAR_DMABUF},
{"video", no_argument, NULL, ARG_VIDEO},
{"hwvideo", no_argument, NULL, ARG_HWVIDEO},
{"threads", required_argument, NULL, ARG_THREADS},
{"display", required_argument, NULL, ARG_DISPLAY},
{"control", required_argument, NULL, ARG_CONTROL},
{0, 0, NULL, 0}};
int main(int argc, char **argv)
......@@ -292,16 +328,16 @@ int main(int argc, char **argv)
char *comp_string = NULL;
char *nthread_string = NULL;
char *wayland_display = NULL;
char *control_path = NULL;
const char *socketpath = NULL;
struct main_config config = {
.n_worker_threads = 0,
struct main_config config = {.n_worker_threads = 0,
.drm_node = NULL,
.compression = COMP_NONE,
.no_gpu = false,
.linear_dmabuf = false,
.video_if_possible = false,
};
.prefer_hwvideo = false};
/* We do not parse any getopt arguments happening after the mode choice
* string, so as not to interfere with them. */
......@@ -320,6 +356,10 @@ int main(int argc, char **argv)
mode = MODE_SERVER;
break;
}
if (!strcmp(argv[mode_argc], "recon")) {
mode = MODE_RECON;
break;
}
mode_argc++;
}
......@@ -331,6 +371,11 @@ int main(int argc, char **argv)
if (opt == -1) {
break;
}
if (mode == MODE_RECON) {
/* no prefix arguments permitted */
fail = true;
continue;
}
switch (opt) {
case 'c':
......@@ -379,6 +424,12 @@ int main(int argc, char **argv)
}
wayland_display = optarg;
break;
case ARG_CONTROL:
if (mode == MODE_CLIENT) {
fail = true;
}
control_path = optarg;
break;
case ARG_UNLINK:
if (mode != MODE_SERVER) {
fail = true;
......@@ -406,6 +457,10 @@ int main(int argc, char **argv)
case ARG_VIDEO:
config.video_if_possible = true;
break;
case ARG_HWVIDEO:
config.video_if_possible = true;
config.prefer_hwvideo = true;
break;
case ARG_THREADS: {
char *endptr;
config.n_worker_threads =
......@@ -423,7 +478,6 @@ int main(int argc, char **argv)
argv += optind;
argc -= optind;
if (fail) {
return usage(EXIT_FAILURE);
} else if (version) {
......@@ -439,6 +493,9 @@ int main(int argc, char **argv)
if (mode == MODE_CLIENT && argc > 1) {
// In client mode, we do not start an application
return usage(EXIT_FAILURE);
} else if (mode == MODE_RECON && argc != 3) {
// The reconnection helper takes exactly two trailing arguments
return usage(EXIT_FAILURE);
}
argv++;
argc--;
......@@ -465,11 +522,11 @@ int main(int argc, char **argv)
sigemptyset(&ca.sa_mask);
ca.sa_flags = SA_RESTART | SA_NOCLDSTOP;
if (sigaction(SIGINT, &ia, NULL) == -1) {
wp_log(WP_ERROR, "Failed to set signal action for SIGINT");
wp_error("Failed to set signal action for SIGINT");
return EXIT_FAILURE;
}
if (sigaction(SIGCHLD, &ca, NULL) == -1) {
wp_log(WP_ERROR, "Failed to set signal action for SIGCHLD");
wp_error("Failed to set signal action for SIGCHLD");
return EXIT_FAILURE;
}
......@@ -478,7 +535,9 @@ int main(int argc, char **argv)
oneshot = true;
}
if (mode == MODE_CLIENT) {
if (mode == MODE_RECON) {
return run_recon(argv[0], argv[1]);
} else if (mode == MODE_CLIENT) {
if (!socketpath) {
socketpath = "/tmp/waypipe-client.sock";
}
......@@ -506,8 +565,9 @@ int main(int argc, char **argv)
sprintf(display_path, "wayland-%s", rbytes);
wayland_display = display_path;
}
return run_server(socketpath, wayland_display, &config, oneshot,
unlink_at_end, application, app_argv);
return run_server(socketpath, wayland_display, control_path,
&config, oneshot, unlink_at_end, application,
app_argv);
} else {
if (!socketpath) {
socketpath = "/tmp/waypipe";
......@@ -553,11 +613,12 @@ int main(int argc, char **argv)
pid_t conn_pid = fork();
if (conn_pid == -1) {
wp_log(WP_ERROR, "Fork failure");
wp_error("Fork failure");
return EXIT_FAILURE;
} else if (conn_pid == 0) {
int nextra = 12 + debug + oneshot +
2 * (remote_drm_node != NULL) +
2 * (control_path != NULL) +
2 * (config.compression != COMP_NONE) +
config.video_if_possible +
2 * needs_login_shell +
......@@ -600,7 +661,10 @@ int main(int argc, char **argv)
"--login-shell";
}
if (config.video_if_possible) {
arglist[dstidx + 1 + offset++] = "--video";
arglist[dstidx + 1 + offset++] =
config.prefer_hwvideo
? "--hwvideo"
: "--video";
}
if (remote_drm_node) {
arglist[dstidx + 1 + offset++] = "--drm-node";
......@@ -611,6 +675,10 @@ int main(int argc, char **argv)
arglist[dstidx + 1 + offset++] = "--threads";
arglist[dstidx + 1 + offset++] = nthread_string;
}
if (control_path) {
arglist[dstidx + 1 + offset++] = "--control";
arglist[dstidx + 1 + offset++] = control_path;
}
arglist[dstidx + 1 + offset++] = "--unlink-socket";
arglist[dstidx + 1 + offset++] = "-s";
arglist[dstidx + 1 + offset++] = serversock;
......@@ -624,7 +692,7 @@ int main(int argc, char **argv)
// execvp effectively frees arglist
execvp(arglist[0], arglist);
wp_log(WP_ERROR, "Fork failed");
wp_error("Fork failed");
free(arglist);
return EXIT_FAILURE;
} else {
......
This diff is collapsed.