weston-debug: Migrate weston_debug_stream to weston_log_wayland file

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
dev
Marius Vlad 5 years ago
parent 8f329e25f7
commit 69e7571e63
  1. 1
      libweston/meson.build
  2. 261
      libweston/weston-debug.c
  3. 5
      libweston/weston-log-internal.h
  4. 295
      libweston/weston-log-wayland.c

@ -26,6 +26,7 @@ srcs_libweston = [
'screenshooter.c', 'screenshooter.c',
'timeline.c', 'timeline.c',
'touch-calibration.c', 'touch-calibration.c',
'weston-log-wayland.c',
'weston-debug.c', 'weston-debug.c',
'zoom.c', 'zoom.c',
'../shared/matrix.c', '../shared/matrix.c',

@ -31,7 +31,6 @@
#include <libweston/libweston.h> #include <libweston/libweston.h>
#include "weston-log-internal.h" #include "weston-log-internal.h"
#include "weston-debug-server-protocol.h" #include "weston-debug-server-protocol.h"
#include <assert.h> #include <assert.h>
@ -108,27 +107,6 @@ struct weston_log_subscription {
weston_log_context::pending_subscription_list */ weston_log_context::pending_subscription_list */
}; };
/** A debug stream created by a client
*
* A client provides a file descriptor for the server to write debug
* messages into. A weston_debug_stream is associated to one
* weston_log_scope via the scope name, and the scope provides the messages.
* There can be several streams for the same scope, all streams getting the
* same messages.
*/
struct weston_debug_stream {
struct weston_log_subscriber base;
int fd; /**< client provided fd */
struct wl_resource *resource; /**< weston_debug_stream_v1 object */
};
static struct weston_debug_stream *
to_weston_debug_stream(struct weston_log_subscriber *sub)
{
return container_of(sub, struct weston_debug_stream, base);
}
/** Creates a new subscription using the subscriber by \c owner. /** Creates a new subscription using the subscriber by \c owner.
* *
* The subscription created is added to the \c owner subscription list. * The subscription created is added to the \c owner subscription list.
@ -286,243 +264,6 @@ weston_debug_protocol_advertise_scopes(struct weston_log_context *log_ctx,
weston_debug_v1_send_available(res, scope->name, scope->desc); weston_debug_v1_send_available(res, scope->name, scope->desc);
} }
static void
stream_close_unlink(struct weston_debug_stream *stream)
{
if (stream->fd != -1)
close(stream->fd);
stream->fd = -1;
}
static void WL_PRINTF(2, 3)
stream_close_on_failure(struct weston_debug_stream *stream,
const char *fmt, ...)
{
char *msg;
va_list ap;
int ret;
stream_close_unlink(stream);
va_start(ap, fmt);
ret = vasprintf(&msg, fmt, ap);
va_end(ap);
if (ret > 0) {
weston_debug_stream_v1_send_failure(stream->resource, msg);
free(msg);
} else {
weston_debug_stream_v1_send_failure(stream->resource,
"MEMFAIL");
}
}
/** Write data into a specific debug stream
*
* \param sub The subscriber's stream to write into; must not be NULL.
* \param[in] data Pointer to the data to write.
* \param len Number of bytes to write.
*
* Writes the given data (binary verbatim) into the debug stream.
* If \c len is zero or negative, the write is silently dropped.
*
* Writing is continued until all data has been written or
* a write fails. If the write fails due to a signal, it is re-tried.
* Otherwise on failure, the stream is closed and
* \c weston_debug_stream_v1.failure event is sent to the client.
*
* \memberof weston_debug_stream
*/
static void
weston_debug_stream_write(struct weston_log_subscriber *sub,
const char *data, size_t len)
{
ssize_t len_ = len;
ssize_t ret;
int e;
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
if (stream->fd == -1)
return;
while (len_ > 0) {
ret = write(stream->fd, data, len_);
e = errno;
if (ret < 0) {
if (e == EINTR)
continue;
stream_close_on_failure(stream,
"Error writing %zd bytes: %s (%d)",
len_, strerror(e), e);
break;
}
len_ -= ret;
data += ret;
}
}
/** Close the debug stream and send success event
*
* \param sub Subscriber's stream to close.
*
* Closes the debug stream and sends \c weston_debug_stream_v1.complete
* event to the client. This tells the client the debug information dump
* is complete.
*
* \memberof weston_debug_stream
*/
static void
weston_debug_stream_complete(struct weston_log_subscriber *sub)
{
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
stream_close_unlink(stream);
weston_debug_stream_v1_send_complete(stream->resource);
}
static void
weston_debug_stream_to_destroy(struct weston_log_subscriber *sub)
{
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
stream_close_on_failure(stream, "debug name removed");
}
static struct weston_debug_stream *
stream_create(struct weston_log_context *log_ctx, const char *name,
int32_t streamfd, struct wl_resource *stream_resource)
{
struct weston_debug_stream *stream;
struct weston_log_scope *scope;
struct weston_log_subscription *sub;
stream = zalloc(sizeof *stream);
if (!stream)
return NULL;
stream->fd = streamfd;
stream->resource = stream_resource;
stream->base.write = weston_debug_stream_write;
stream->base.destroy = weston_debug_stream_to_destroy;
stream->base.complete = weston_debug_stream_complete;
wl_list_init(&stream->base.subscription_list);
sub = weston_log_subscription_create(&stream->base, name);
scope = weston_log_get_scope(log_ctx, name);
if (scope) {
weston_log_subscription_add(scope, sub);
if (scope->begin_cb)
scope->begin_cb(scope, scope->user_data);
} else {
stream_close_on_failure(stream,
"Debug stream name '%s' is unknown.",
name);
}
return stream;
}
static void
stream_destroy(struct wl_resource *stream_resource)
{
struct weston_debug_stream *stream;
struct weston_log_subscription *sub = NULL;
stream = wl_resource_get_user_data(stream_resource);
if (stream->fd != -1)
close(stream->fd);
sub = weston_log_subscriber_get_only_subscription(&stream->base);
weston_log_subscription_remove(sub);
weston_log_subscription_destroy(sub);
free(stream);
}
static void
weston_debug_stream_destroy(struct wl_client *client,
struct wl_resource *stream_resource)
{
wl_resource_destroy(stream_resource);
}
static const struct weston_debug_stream_v1_interface
weston_debug_stream_impl = {
weston_debug_stream_destroy
};
static void
weston_debug_destroy(struct wl_client *client,
struct wl_resource *global_resource)
{
wl_resource_destroy(global_resource);
}
static void
weston_debug_subscribe(struct wl_client *client,
struct wl_resource *global_resource,
const char *name,
int32_t streamfd,
uint32_t new_stream_id)
{
struct weston_log_context *log_ctx;
struct wl_resource *stream_resource;
uint32_t version;
struct weston_debug_stream *stream;
log_ctx = wl_resource_get_user_data(global_resource);
version = wl_resource_get_version(global_resource);
stream_resource = wl_resource_create(client,
&weston_debug_stream_v1_interface,
version, new_stream_id);
if (!stream_resource)
goto fail;
stream = stream_create(log_ctx, name, streamfd, stream_resource);
if (!stream)
goto fail;
wl_resource_set_implementation(stream_resource,
&weston_debug_stream_impl,
stream, stream_destroy);
return;
fail:
close(streamfd);
wl_client_post_no_memory(client);
}
static const struct weston_debug_v1_interface weston_debug_impl = {
weston_debug_destroy,
weston_debug_subscribe
};
static void
bind_weston_debug(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
struct weston_log_context *log_ctx = data;
struct wl_resource *resource;
resource = wl_resource_create(client,
&weston_debug_v1_interface,
version, id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(resource, &weston_debug_impl,
log_ctx, NULL);
weston_debug_protocol_advertise_scopes(log_ctx, resource);
}
/** /**
* Connect weston_compositor structure to weston_log_context structure. * Connect weston_compositor structure to weston_log_context structure.
* *
@ -620,7 +361,7 @@ weston_compositor_enable_debug_protocol(struct weston_compositor *compositor)
log_ctx->global = wl_global_create(compositor->wl_display, log_ctx->global = wl_global_create(compositor->wl_display,
&weston_debug_v1_interface, 1, &weston_debug_v1_interface, 1,
log_ctx, bind_weston_debug); log_ctx, weston_log_bind_weston_debug);
if (!log_ctx->global) if (!log_ctx->global)
return; return;

@ -77,6 +77,11 @@ weston_log_subscription_add(struct weston_log_scope *scope,
void void
weston_log_subscription_remove(struct weston_log_subscription *sub); weston_log_subscription_remove(struct weston_log_subscription *sub);
void
weston_log_bind_weston_debug(struct wl_client *client,
void *data, uint32_t version, uint32_t id);
struct weston_log_scope * struct weston_log_scope *
weston_log_get_scope(struct weston_log_context *log_ctx, const char *name); weston_log_get_scope(struct weston_log_context *log_ctx, const char *name);

@ -0,0 +1,295 @@
/*
* Copyright © 2019 Collabora Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include <libweston/weston-debug.h>
#include "helpers.h"
#include <libweston/libweston.h>
#include "weston-log-internal.h"
#include "weston-debug-server-protocol.h"
#include <assert.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
/** A debug stream created by a client
*
* A client provides a file descriptor for the server to write debug
* messages into. A weston_debug_stream is associated to one
* weston_log_scope via the scope name, and the scope provides the messages.
* There can be several streams for the same scope, all streams getting the
* same messages.
*/
struct weston_debug_stream {
struct weston_log_subscriber base;
int fd; /**< client provided fd */
struct wl_resource *resource; /**< weston_debug_stream_v1 object */
};
static struct weston_debug_stream *
to_weston_debug_stream(struct weston_log_subscriber *sub)
{
return container_of(sub, struct weston_debug_stream, base);
}
static void
stream_close_unlink(struct weston_debug_stream *stream)
{
if (stream->fd != -1)
close(stream->fd);
stream->fd = -1;
}
static void WL_PRINTF(2, 3)
stream_close_on_failure(struct weston_debug_stream *stream,
const char *fmt, ...)
{
char *msg;
va_list ap;
int ret;
stream_close_unlink(stream);
va_start(ap, fmt);
ret = vasprintf(&msg, fmt, ap);
va_end(ap);
if (ret > 0) {
weston_debug_stream_v1_send_failure(stream->resource, msg);
free(msg);
} else {
weston_debug_stream_v1_send_failure(stream->resource,
"MEMFAIL");
}
}
/** Write data into a specific debug stream
*
* \param sub The subscriber's stream to write into; must not be NULL.
* \param[in] data Pointer to the data to write.
* \param len Number of bytes to write.
*
* Writes the given data (binary verbatim) into the debug stream.
* If \c len is zero or negative, the write is silently dropped.
*
* Writing is continued until all data has been written or
* a write fails. If the write fails due to a signal, it is re-tried.
* Otherwise on failure, the stream is closed and
* \c weston_debug_stream_v1.failure event is sent to the client.
*
* \memberof weston_debug_stream
*/
static void
weston_debug_stream_write(struct weston_log_subscriber *sub,
const char *data, size_t len)
{
ssize_t len_ = len;
ssize_t ret;
int e;
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
if (stream->fd == -1)
return;
while (len_ > 0) {
ret = write(stream->fd, data, len_);
e = errno;
if (ret < 0) {
if (e == EINTR)
continue;
stream_close_on_failure(stream,
"Error writing %zd bytes: %s (%d)",
len_, strerror(e), e);
break;
}
len_ -= ret;
data += ret;
}
}
/** Close the debug stream and send success event
*
* \param sub Subscriber's stream to close.
*
* Closes the debug stream and sends \c weston_debug_stream_v1.complete
* event to the client. This tells the client the debug information dump
* is complete.
*
* \memberof weston_debug_stream
*/
static void
weston_debug_stream_complete(struct weston_log_subscriber *sub)
{
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
stream_close_unlink(stream);
weston_debug_stream_v1_send_complete(stream->resource);
}
static void
weston_debug_stream_to_destroy(struct weston_log_subscriber *sub)
{
struct weston_debug_stream *stream = to_weston_debug_stream(sub);
stream_close_on_failure(stream, "debug name removed");
}
static struct weston_debug_stream *
stream_create(struct weston_log_context *log_ctx, const char *name,
int32_t streamfd, struct wl_resource *stream_resource)
{
struct weston_debug_stream *stream;
struct weston_log_scope *scope;
struct weston_log_subscription *sub;
stream = zalloc(sizeof *stream);
if (!stream)
return NULL;
stream->fd = streamfd;
stream->resource = stream_resource;
stream->base.write = weston_debug_stream_write;
stream->base.destroy = weston_debug_stream_to_destroy;
stream->base.complete = weston_debug_stream_complete;
wl_list_init(&stream->base.subscription_list);
scope = weston_log_get_scope(log_ctx, name);
if (scope) {
sub = weston_log_subscription_create(&stream->base, name);
weston_log_subscription_add(scope, sub);
weston_log_run_begin_cb(scope);
} else {
stream_close_on_failure(stream,
"Debug stream name '%s' is unknown.",
name);
}
return stream;
}
static void
stream_destroy(struct wl_resource *stream_resource)
{
struct weston_debug_stream *stream;
struct weston_log_subscription *sub = NULL;
stream = wl_resource_get_user_data(stream_resource);
if (stream->fd != -1)
close(stream->fd);
sub = weston_log_subscriber_get_only_subscription(&stream->base);
weston_log_subscription_remove(sub);
weston_log_subscription_destroy(sub);
free(stream);
}
static void
weston_debug_stream_destroy(struct wl_client *client,
struct wl_resource *stream_resource)
{
wl_resource_destroy(stream_resource);
}
static const struct weston_debug_stream_v1_interface
weston_debug_stream_impl = {
weston_debug_stream_destroy
};
static void
weston_debug_destroy(struct wl_client *client,
struct wl_resource *global_resource)
{
wl_resource_destroy(global_resource);
}
static void
weston_debug_subscribe(struct wl_client *client,
struct wl_resource *global_resource,
const char *name,
int32_t streamfd,
uint32_t new_stream_id)
{
struct weston_log_context *log_ctx;
struct wl_resource *stream_resource;
uint32_t version;
struct weston_debug_stream *stream;
log_ctx = wl_resource_get_user_data(global_resource);
version = wl_resource_get_version(global_resource);
stream_resource = wl_resource_create(client,
&weston_debug_stream_v1_interface,
version, new_stream_id);
if (!stream_resource)
goto fail;
stream = stream_create(log_ctx, name, streamfd, stream_resource);
if (!stream)
goto fail;
wl_resource_set_implementation(stream_resource,
&weston_debug_stream_impl,
stream, stream_destroy);
return;
fail:
close(streamfd);
wl_client_post_no_memory(client);
}
static const struct weston_debug_v1_interface weston_debug_impl = {
weston_debug_destroy,
weston_debug_subscribe
};
void
weston_log_bind_weston_debug(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
struct weston_log_context *log_ctx = data;
struct wl_resource *resource;
resource = wl_resource_create(client,
&weston_debug_v1_interface,
version, id);
if (!resource) {
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(resource, &weston_debug_impl,
log_ctx, NULL);
weston_debug_protocol_advertise_scopes(log_ctx, resource);
}
Loading…
Cancel
Save