mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-15 07:00:05 -05:00
Add support for trace logging in lockfree ringbuffer
Fix some crashes when the connection is dead. Small cleanups in the audio mixer Only propose alloc_buffer when we are using export_buf in v4l2
This commit is contained in:
parent
b51d3e4862
commit
214a0e27d8
10 changed files with 248 additions and 83 deletions
|
|
@ -37,7 +37,7 @@ typedef struct {
|
|||
|
||||
int fd;
|
||||
PinosConnection *connection;
|
||||
SpaSource source;
|
||||
SpaSource *source;
|
||||
|
||||
bool disconnecting;
|
||||
PinosListener need_flush;
|
||||
|
|
@ -388,7 +388,8 @@ do_flush_event (SpaLoopUtils *utils,
|
|||
{
|
||||
PinosContextImpl *impl = data;
|
||||
if (impl->connection)
|
||||
pinos_connection_flush (impl->connection);
|
||||
if (!pinos_connection_flush (impl->connection))
|
||||
pinos_context_disconnect (&impl->this);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -633,12 +634,12 @@ pinos_context_connect_fd (PinosContext *context,
|
|||
|
||||
impl->fd = fd;
|
||||
|
||||
pinos_loop_add_io (context->loop,
|
||||
fd,
|
||||
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
|
||||
false,
|
||||
on_context_data,
|
||||
impl);
|
||||
impl->source = pinos_loop_add_io (context->loop,
|
||||
fd,
|
||||
SPA_IO_IN | SPA_IO_HUP | SPA_IO_ERR,
|
||||
false,
|
||||
on_context_data,
|
||||
impl);
|
||||
|
||||
context->core_proxy = pinos_proxy_new (context,
|
||||
0,
|
||||
|
|
@ -673,6 +674,7 @@ pinos_context_connect_fd (PinosContext *context,
|
|||
no_registry:
|
||||
pinos_proxy_destroy (context->core_proxy);
|
||||
no_proxy:
|
||||
pinos_loop_destroy_source (context->loop, impl->source);
|
||||
pinos_connection_destroy (impl->connection);
|
||||
error_close:
|
||||
close (fd);
|
||||
|
|
@ -694,6 +696,10 @@ pinos_context_disconnect (PinosContext *context)
|
|||
|
||||
impl->disconnecting = true;
|
||||
|
||||
if (impl->source)
|
||||
pinos_loop_destroy_source (context->loop, impl->source);
|
||||
impl->source = NULL;
|
||||
|
||||
if (context->registry_proxy)
|
||||
pinos_proxy_destroy (context->registry_proxy);
|
||||
context->registry_proxy = NULL;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <spa/ringbuffer.h>
|
||||
|
||||
#include <pinos/client/log.h>
|
||||
|
||||
|
|
@ -25,6 +29,15 @@
|
|||
|
||||
SpaLogLevel pinos_log_level = DEFAULT_LOG_LEVEL;
|
||||
|
||||
#define TRACE_BUFFER (16*1024)
|
||||
|
||||
typedef struct {
|
||||
SpaLog log;
|
||||
SpaRingbuffer trace_rb;
|
||||
uint8_t trace_data[TRACE_BUFFER];
|
||||
SpaSource *source;
|
||||
} DebugLog;
|
||||
|
||||
static void
|
||||
do_logv (SpaLog *log,
|
||||
SpaLogLevel level,
|
||||
|
|
@ -34,22 +47,28 @@ do_logv (SpaLog *log,
|
|||
const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
char text[16*1024], location[128];
|
||||
static const char *levels[] = {
|
||||
"-",
|
||||
"E",
|
||||
"W",
|
||||
"I",
|
||||
"D",
|
||||
"T",
|
||||
};
|
||||
DebugLog *l = SPA_CONTAINER_OF (log, DebugLog, log);
|
||||
char text[1024], location[1024];
|
||||
static const char *levels[] = { "-", "E", "W", "I", "D", "T", };
|
||||
int size;
|
||||
|
||||
vsnprintf (text, sizeof(text), fmt, args);
|
||||
if (1) {
|
||||
snprintf (location, sizeof(location), "%s:%i %s()", strrchr (file, '/')+1, line, func);
|
||||
fprintf(stderr, "[%s][%s] %s\n", levels[level], location, text);
|
||||
} else {
|
||||
fprintf(stderr, "[%s] %s\n", levels[level], text);
|
||||
}
|
||||
size = snprintf (location, sizeof(location), "[%s][%s:%i %s()] %s\n",
|
||||
levels[level], strrchr (file, '/')+1, line, func, text);
|
||||
|
||||
if (SPA_UNLIKELY (level == SPA_LOG_LEVEL_TRACE && l->source)) {
|
||||
uint32_t index;
|
||||
uint64_t count = 1;
|
||||
|
||||
spa_ringbuffer_get_write_index (&l->trace_rb, &index);
|
||||
spa_ringbuffer_write_data (&l->trace_rb, l->trace_data,
|
||||
index & l->trace_rb.mask,
|
||||
location, size);
|
||||
spa_ringbuffer_write_update (&l->trace_rb, index + size);
|
||||
|
||||
write (l->source->fd, &count, sizeof(uint64_t));
|
||||
} else
|
||||
fputs (location, stderr);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -66,25 +85,63 @@ do_log (SpaLog *log,
|
|||
va_end (args);
|
||||
}
|
||||
|
||||
static SpaLog log = {
|
||||
sizeof (SpaLog),
|
||||
NULL,
|
||||
DEFAULT_LOG_LEVEL,
|
||||
do_log,
|
||||
do_logv,
|
||||
static DebugLog log = {
|
||||
{ sizeof (SpaLog),
|
||||
NULL,
|
||||
DEFAULT_LOG_LEVEL,
|
||||
do_log,
|
||||
do_logv,
|
||||
},
|
||||
{ 0, 0, TRACE_BUFFER, TRACE_BUFFER - 1 },
|
||||
};
|
||||
|
||||
SpaLog *
|
||||
pinos_log_get (void)
|
||||
{
|
||||
return &log;
|
||||
return &log.log;
|
||||
}
|
||||
|
||||
void
|
||||
pinos_log_set_level (SpaLogLevel level)
|
||||
{
|
||||
pinos_log_level = level;
|
||||
log.level = level;
|
||||
log.log.level = level;
|
||||
}
|
||||
|
||||
static void
|
||||
on_trace_event (SpaSource *source)
|
||||
{
|
||||
int32_t avail;
|
||||
uint32_t index;
|
||||
uint64_t count;
|
||||
|
||||
if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
|
||||
fprintf (stderr, "failed to read event fd: %s", strerror (errno));
|
||||
|
||||
while ((avail = spa_ringbuffer_get_read_index (&log.trace_rb, &index)) > 0) {
|
||||
uint32_t offset, first, written;
|
||||
|
||||
if (avail > log.trace_rb.size) {
|
||||
index += avail - log.trace_rb.size;
|
||||
avail = log.trace_rb.size;
|
||||
}
|
||||
offset = index & log.trace_rb.mask;
|
||||
first = SPA_MIN (avail, log.trace_rb.size - offset);
|
||||
|
||||
written = fprintf (stderr, "%*s", first, log.trace_data + offset);
|
||||
if (SPA_UNLIKELY (avail > first)) {
|
||||
written += fprintf (stderr, "%*s", avail - first, log.trace_data + first);
|
||||
}
|
||||
spa_ringbuffer_read_update (&log.trace_rb, index + written);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pinos_log_set_trace_event (SpaSource *source)
|
||||
{
|
||||
log.source = source;
|
||||
log.source->func = on_trace_event;
|
||||
log.source->data = &log;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -97,7 +154,7 @@ pinos_log_log (SpaLogLevel level,
|
|||
if (SPA_UNLIKELY (pinos_log_level_enabled (level))) {
|
||||
va_list args;
|
||||
va_start (args, fmt);
|
||||
do_logv (&log, level, file, line, func, fmt, args);
|
||||
do_logv (&log.log, level, file, line, func, fmt, args);
|
||||
va_end (args);
|
||||
}
|
||||
}
|
||||
|
|
@ -111,6 +168,6 @@ pinos_log_logv (SpaLogLevel level,
|
|||
va_list args)
|
||||
{
|
||||
if (SPA_UNLIKELY (pinos_log_level_enabled (level))) {
|
||||
do_logv (&log, level, file, line, func, fmt, args);
|
||||
do_logv (&log.log, level, file, line, func, fmt, args);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define __PINOS_LOG_H__
|
||||
|
||||
#include <spa/log.h>
|
||||
#include <spa/loop.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -31,6 +32,8 @@ extern SpaLogLevel pinos_log_level;
|
|||
SpaLog * pinos_log_get (void);
|
||||
|
||||
void pinos_log_set_level (SpaLogLevel level);
|
||||
void pinos_log_set_trace_event (SpaSource *source);
|
||||
|
||||
|
||||
void pinos_log_log (SpaLogLevel level,
|
||||
const char *file,
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ core_marshal_client_update (void *object,
|
|||
SpaPODFrame f;
|
||||
int i, n_items;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
n_items = props ? props->n_items : 0;
|
||||
|
|
@ -107,6 +110,9 @@ core_marshal_sync (void *object,
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
|
|
@ -124,6 +130,9 @@ core_marshal_get_registry (void *object,
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
|
|
@ -145,6 +154,9 @@ core_marshal_create_node (void *object,
|
|||
SpaPODFrame f;
|
||||
uint32_t i, n_items;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
n_items = props ? props->n_items : 0;
|
||||
|
|
@ -180,6 +192,9 @@ core_marshal_create_client_node (void *object,
|
|||
SpaPODFrame f;
|
||||
uint32_t i, n_items;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
n_items = props ? props->n_items : 0;
|
||||
|
|
@ -214,6 +229,9 @@ core_marshal_update_types (void *object,
|
|||
SpaPODFrame f;
|
||||
uint32_t i;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
spa_pod_builder_add (&b.b,
|
||||
SPA_POD_TYPE_STRUCT, &f,
|
||||
SPA_POD_TYPE_INT, first_id,
|
||||
|
|
@ -460,6 +478,9 @@ client_node_marshal_update (void *object,
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
|
|
@ -488,6 +509,9 @@ client_node_marshal_port_update (void *object,
|
|||
SpaPODFrame f[2];
|
||||
int i, n_items;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_add (&b.b,
|
||||
|
|
@ -546,6 +570,9 @@ client_node_marshal_event (void *object,
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
|
|
@ -562,6 +589,9 @@ client_node_marshal_destroy (void *object)
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f, 0);
|
||||
|
|
@ -990,6 +1020,9 @@ registry_marshal_bind (void *object,
|
|||
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
|
||||
SpaPODFrame f;
|
||||
|
||||
if (connection == NULL)
|
||||
return;
|
||||
|
||||
core_update_map (proxy->context);
|
||||
|
||||
spa_pod_builder_struct (&b.b, &f,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue