Plug some leaks

Add maxsize to bufferdata in case the memory size can be variable such
as with encoded formats. Copy new size in the proxy.
This commit is contained in:
Wim Taymans 2016-09-30 19:56:41 +02:00
parent 9d4048e73a
commit b208e8b690
15 changed files with 117 additions and 57 deletions

View file

@ -389,12 +389,12 @@ on_add_buffer (GObject *gobject,
gint fd = *(int*)d->data;
fdmem = gst_fd_allocator_alloc (pinossink->allocator, dup (fd),
d->offset + d->size, GST_FD_MEMORY_FLAG_NONE);
d->offset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (fdmem, d->offset, d->size);
gst_buffer_append_memory (buf, fdmem);
} else {
gst_buffer_append_memory (buf,
gst_memory_new_wrapped (0, d->data, d->offset + d->size, d->offset,
gst_memory_new_wrapped (0, d->data, d->offset + d->maxsize, d->offset,
d->size, NULL, NULL));
}
}

View file

@ -404,10 +404,10 @@ on_add_buffer (GObject *gobject,
gint fd = SPA_PTR_TO_INT (d->data);
gmem = gst_fd_allocator_alloc (pinossrc->fd_allocator, dup (fd),
d->offset + d->size, GST_FD_MEMORY_FLAG_NONE);
d->offset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
gst_memory_resize (gmem, d->offset, d->size);
} else {
gmem = gst_memory_new_wrapped (0, d->data, d->offset + d->size, d->offset,
gmem = gst_memory_new_wrapped (0, d->data, d->offset + d->maxsize, d->offset,
d->size, NULL, NULL);
}
gst_buffer_append_memory (buf, gmem);

View file

@ -491,6 +491,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
this->input->buffers = priv->buffers;
this->input->n_buffers = priv->n_buffers;
this->input->allocated = TRUE;
this->input->buffer_mem = priv->buffer_mem;
priv->allocated = FALSE;
g_debug ("allocated %d buffers %p from input port", priv->n_buffers, priv->buffers);
}
@ -507,6 +508,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
this->output->buffers = priv->buffers;
this->output->n_buffers = priv->n_buffers;
this->output->allocated = TRUE;
this->output->buffer_mem = priv->buffer_mem;
priv->allocated = FALSE;
g_debug ("allocated %d buffers %p from output port", priv->n_buffers, priv->buffers);
}

View file

@ -29,6 +29,7 @@ typedef struct _PinosLinkClass PinosLinkClass;
typedef struct _PinosLinkPrivate PinosLinkPrivate;
#include <pinos/server/daemon.h>
#include <pinos/server/utils.h>
#include <spa/include/spa/ringbuffer.h>
#define PINOS_TYPE_LINK (pinos_link_get_type ())
@ -41,11 +42,12 @@ typedef struct _PinosLinkPrivate PinosLinkPrivate;
#define PINOS_LINK_CLASS_CAST(klass)((PinosLinkClass*)(klass))
typedef struct {
PinosNode *node;
uint32_t port;
gboolean allocated;
SpaBuffer **buffers;
guint n_buffers;
PinosNode *node;
uint32_t port;
gboolean allocated;
PinosMemblock buffer_mem;
SpaBuffer **buffers;
guint n_buffers;
} PinosPort;
/**

View file

@ -285,6 +285,8 @@ suspend_node (PinosNode *this)
g_warning ("error unset format output: %d", res);
p->port.buffers = NULL;
p->port.n_buffers = 0;
if (p->port.allocated)
pinos_memblock_free (&p->port.buffer_mem);
p->port.allocated = FALSE;
}
for (walk = priv->output_ports; walk; walk = g_list_next (walk)) {
@ -293,6 +295,8 @@ suspend_node (PinosNode *this)
g_warning ("error unset format output: %d", res);
p->port.buffers = NULL;
p->port.n_buffers = 0;
if (p->port.allocated)
pinos_memblock_free (&p->port.buffer_mem);
p->port.allocated = FALSE;
}
return res;

View file

@ -24,11 +24,14 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include "memfd-wrappers.h"
#include <pinos/server/utils.h>
#undef USE_MEMFD
gboolean
pinos_memblock_alloc (PinosMemblockFlags flags,
gsize size,
@ -41,19 +44,35 @@ pinos_memblock_alloc (PinosMemblockFlags flags,
mem->size = size;
if (flags & PINOS_MEMBLOCK_FLAG_WITH_FD) {
#ifdef USE_MEMFD
mem->fd = memfd_create ("pinos-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (mem->fd == -1) {
fprintf (stderr, "Failed to create memfd: %s\n", strerror (errno));
return FALSE;
}
#else
char filename[] = "/dev/shm/spa-tmpfile.XXXXXX";
mem->fd = mkostemp (filename, O_CLOEXEC);
if (mem->fd == -1) {
fprintf (stderr, "Failed to create temporary file: %s\n", strerror (errno));
return FALSE;
}
unlink (filename);
#endif
if (ftruncate (mem->fd, size) < 0) {
g_warning ("Failed to truncate temporary file: %s", strerror (errno));
close (mem->fd);
return FALSE;
}
#ifdef USE_MEMFD
if (flags & PINOS_MEMBLOCK_FLAG_SEAL) {
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
if (fcntl (mem->fd, F_ADD_SEALS, seals) == -1) {
g_warning ("Failed to add seals: %s", strerror (errno));
}
}
#endif
if (flags & PINOS_MEMBLOCK_FLAG_MAP_READWRITE) {
int prot = 0;

View file

@ -26,8 +26,6 @@ G_BEGIN_DECLS
typedef struct _PinosMemblock PinosMemblock;
#include <pinos/server/daemon.h>
typedef enum {
PINOS_MEMBLOCK_FLAG_NONE = 0,
PINOS_MEMBLOCK_FLAG_WITH_FD = (1 << 0),

View file

@ -132,7 +132,8 @@ typedef enum {
* @type: memory type
* @data: pointer to memory
* @offset: offset in @data
* @size: size of @data
* @size: valid size of @data
* @maxsize: size of @data
* @stride: stride of data if applicable
*/
typedef struct {
@ -140,6 +141,7 @@ typedef struct {
void *data;
off_t offset;
size_t size;
size_t maxsize;
ssize_t stride;
} SpaData;

View file

@ -188,7 +188,7 @@ spa_prop_info_fill_audio (SpaPropInfo *info,
return SPA_RESULT_INVALID_PROPERTY_INDEX;
memcpy (info, &format_prop_info[i], sizeof (SpaPropInfo));
info->offset = offset;
info->offset = offset - sizeof (SpaFormat) + sizeof (SpaProps);
return SPA_RESULT_OK;
}

View file

@ -122,11 +122,12 @@ spa_debug_buffer (const SpaBuffer *buffer)
fprintf (stderr, " n_datas: \t%u (at %p)\n", buffer->n_datas, buffer->datas);
for (i = 0; i < buffer->n_datas; i++) {
SpaData *d = &buffer->datas[i];
fprintf (stderr, " type: %d\n", d->type);
fprintf (stderr, " data: %p\n", d->data);
fprintf (stderr, " offset: %zd\n", d->offset);
fprintf (stderr, " size: %zd\n", d->size);
fprintf (stderr, " stride: %zd\n", d->stride);
fprintf (stderr, " type: %d\n", d->type);
fprintf (stderr, " data: %p\n", d->data);
fprintf (stderr, " offset: %zd\n", d->offset);
fprintf (stderr, " size: %zd\n", d->size);
fprintf (stderr, " maxsize: %zd\n", d->maxsize);
fprintf (stderr, " stride: %zd\n", d->stride);
}
return SPA_RESULT_OK;
}

View file

@ -73,7 +73,7 @@ struct _SpaAudioMixer {
int port_count;
int port_queued;
SpaAudioMixerPort ports[MAX_PORTS];
SpaAudioMixerPort ports[MAX_PORTS + 1];
};
enum {
@ -224,13 +224,13 @@ spa_audiomixer_node_get_port_ids (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (input_ids) {
for (i = 1, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
if (this->ports[i].valid)
input_ids[idx++] = i;
}
}
if (n_output_ports > 0 && output_ids)
output_ids[0] = 0;
output_ids[0] = MAX_PORTS;
return SPA_RESULT_OK;
}
@ -261,7 +261,7 @@ spa_audiomixer_node_add_port (SpaNode *node,
SPA_PORT_INFO_FLAG_IN_PLACE;
this->ports[port_id].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT;
this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
this->ports[MAX_PORTS].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
return SPA_RESULT_OK;
}
@ -277,7 +277,7 @@ spa_audiomixer_node_remove_port (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id == 0 || port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
this->ports[port_id].valid = false;
@ -287,7 +287,7 @@ spa_audiomixer_node_remove_port (SpaNode *node,
this->port_queued--;
}
if (this->port_count == this->port_queued)
this->ports[0].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
this->ports[MAX_PORTS].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT;
return SPA_RESULT_OK;
}
@ -377,7 +377,7 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -403,7 +403,7 @@ spa_audiomixer_node_port_get_info (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -469,7 +469,7 @@ spa_audiomixer_node_port_get_status (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (port_id >= MAX_PORTS || !this->ports[port_id].valid)
if (port_id > MAX_PORTS || !this->ports[port_id].valid)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[port_id];
@ -495,7 +495,7 @@ spa_audiomixer_node_port_push_input (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (this->ports[0].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT)
if (this->ports[MAX_PORTS].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT)
return SPA_RESULT_HAVE_ENOUGH_INPUT;
for (i = 0; i < n_info; i++) {
@ -673,7 +673,7 @@ spa_audiomixer_node_port_pull_output (SpaNode *node,
this = (SpaAudioMixer *) node->handle;
if (info->port_id != 0)
if (info->port_id != MAX_PORTS)
return SPA_RESULT_INVALID_PORT;
port = &this->ports[info->port_id];
@ -781,10 +781,10 @@ spa_audiomixer_init (const SpaHandleFactory *factory,
this->props[1].props.prop_info = prop_info;
reset_audiomixer_props (&this->props[1]);
this->ports[0].valid = true;
this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
this->ports[MAX_PORTS].valid = true;
this->ports[MAX_PORTS].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS |
SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
return SPA_RESULT_OK;
}

View file

@ -418,6 +418,27 @@ do_update_port (SpaProxy *this,
}
}
static void
clear_port (SpaProxy *this,
SpaProxyPort *port,
uint32_t port_id)
{
SpaControlCmdPortUpdate pu;
pu.change_mask = SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS |
SPA_CONTROL_CMD_PORT_UPDATE_FORMAT |
SPA_CONTROL_CMD_PORT_UPDATE_PROPS |
SPA_CONTROL_CMD_PORT_UPDATE_INFO;
pu.port_id = port_id;
pu.n_possible_formats = 0;
pu.possible_formats = NULL;
pu.format = NULL;
pu.props = NULL;
pu.info = NULL;
do_update_port (this, &pu);
clear_buffers (this, port);
}
static void
do_uninit_port (SpaProxy *this,
uint32_t port_id)
@ -432,10 +453,8 @@ do_uninit_port (SpaProxy *this,
else
this->n_outputs--;
clear_port (this, port, port_id);
port->valid = false;
if (port->format)
free (port->format);
port->format = NULL;
}
static SpaResult
@ -443,7 +462,7 @@ spa_proxy_node_add_port (SpaNode *node,
uint32_t port_id)
{
SpaProxy *this;
SpaControlCmdPortUpdate pu;
SpaProxyPort *port;
if (node == NULL || node->handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -453,17 +472,8 @@ spa_proxy_node_add_port (SpaNode *node,
if (!CHECK_FREE_PORT_ID (this, port_id))
return SPA_RESULT_INVALID_PORT;
pu.change_mask = SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS |
SPA_CONTROL_CMD_PORT_UPDATE_FORMAT |
SPA_CONTROL_CMD_PORT_UPDATE_PROPS |
SPA_CONTROL_CMD_PORT_UPDATE_INFO;
pu.port_id = port_id;
pu.n_possible_formats = 0;
pu.possible_formats = NULL;
pu.format = NULL;
pu.props = NULL;
pu.info = NULL;
do_update_port (this, &pu);
port = &this->ports[port_id];
clear_port (this, port, port_id);
return SPA_RESULT_OK;
}
@ -714,7 +724,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
am.fd_index = spa_control_builder_add_fd (&builder, SPA_PTR_TO_INT (d->data), false);
am.flags = 0;
am.offset = d->offset;
am.size = d->size;
am.size = d->maxsize;
spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am);
b->buffer.datas[j].data = SPA_UINT32_TO_PTR (n_mem);
@ -732,12 +742,14 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
close (port->buffer_mem_fd);
return SPA_RESULT_ERROR;
}
#if 0
{
unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
if (fcntl (port->buffer_mem_fd, F_ADD_SEALS, seals) == -1) {
fprintf (stderr, "Failed to add seals: %s\n", strerror (errno));
}
}
#endif
p = port->buffer_mem_ptr = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, port->buffer_mem_fd, 0);
for (i = 0; i < n_buffers; i++) {
@ -749,6 +761,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node,
len = spa_buffer_serialize (p, &b->buffer);
sb = p;
b->buffer.datas = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->datas), SpaData);
sbm = SPA_MEMBER (sb, SPA_PTR_TO_INT (sb->metas), SpaMeta);
for (j = 0; j < b->buffer.n_metas; j++)
@ -869,6 +882,9 @@ copy_meta (SpaProxy *this, SpaProxyPort *port, uint32_t buffer_id)
SpaMeta *dm = &b->buffer.metas[i];
memcpy (dm->data, sm->data, dm->size);
}
for (i = 0; i < b->outbuf->n_datas; i++) {
b->buffer.datas[i].size = b->outbuf->datas[i].size;
}
}
static SpaResult
@ -1223,6 +1239,19 @@ spa_proxy_get_interface (SpaHandle *handle,
static SpaResult
proxy_clear (SpaHandle *handle)
{
SpaProxy *this;
unsigned int i;
if (handle == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = (SpaProxy *) handle;
for (i = 0; i < MAX_PORTS; i++) {
if (this->ports[i].valid)
clear_port (this, &this->ports[i], i);
}
return SPA_RESULT_OK;
}

View file

@ -948,7 +948,7 @@ spa_v4l2_use_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_buffe
b->v4l2_buffer.memory = state->memtype;
b->v4l2_buffer.index = i;
b->v4l2_buffer.m.userptr = (unsigned long) SPA_MEMBER (d[0].data, d[0].offset, void *);
b->v4l2_buffer.length = d[0].size;
b->v4l2_buffer.length = d[0].maxsize;
spa_v4l2_buffer_recycle (this, buffers[i]->id);
}
@ -1017,6 +1017,7 @@ mmap_init (SpaV4l2Source *this,
d = buffers[i]->datas;
d[0].offset = 0;
d[0].size = b->v4l2_buffer.length;
d[0].maxsize = b->v4l2_buffer.length;
d[0].stride = state->fmt.fmt.pix.bytesperline;
if (state->export_buf) {

View file

@ -179,7 +179,7 @@ make_nodes (AppData *data)
SpaProps *props;
SpaPropValue value;
if ((res = make_node (&data->sink, "plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) {
if ((res = make_node (&data->sink, "spa/plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) {
printf ("can't create alsa-sink: %d\n", res);
return res;
}
@ -188,7 +188,7 @@ make_nodes (AppData *data)
if ((res = spa_node_get_props (data->sink, &props)) < 0)
printf ("got get_props error %d\n", res);
value.value = "hw:0";
value.value = "hw:1";
value.size = strlen (value.value)+1;
spa_props_set_value (props, spa_props_index_for_name (props, "device"), &value);
@ -196,17 +196,17 @@ make_nodes (AppData *data)
printf ("got set_props error %d\n", res);
if ((res = make_node (&data->mix, "plugins/audiomixer/libspa-audiomixer.so", "audiomixer")) < 0) {
if ((res = make_node (&data->mix, "spa/plugins/audiomixer/libspa-audiomixer.so", "audiomixer")) < 0) {
printf ("can't create audiomixer: %d\n", res);
return res;
}
spa_node_set_event_callback (data->mix, on_mix_event, data);
if ((res = make_node (&data->source1, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
if ((res = make_node (&data->source1, "spa/plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
printf ("can't create audiotestsrc: %d\n", res);
return res;
}
if ((res = make_node (&data->source2, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
if ((res = make_node (&data->source2, "spa/plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) {
printf ("can't create audiotestsrc: %d\n", res);
return res;
}
@ -247,7 +247,7 @@ negotiate_formats (AppData *data)
if ((res = spa_node_port_set_format (data->sink, 0, false, format)) < 0)
return res;
if ((res = spa_node_port_set_format (data->mix, 0, false, format)) < 0)
if ((res = spa_node_port_set_format (data->mix, 128, false, format)) < 0)
return res;
data->mix_ports[0] = 0;
@ -260,7 +260,7 @@ negotiate_formats (AppData *data)
if ((res = spa_node_port_set_format (data->source1, 0, false, format)) < 0)
return res;
data->mix_ports[1] = 0;
data->mix_ports[1] = 1;
if ((res = spa_node_add_port (data->mix, 1)) < 0)
return res;

View file

@ -152,6 +152,7 @@ on_source_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
datas[0].data = sdata;
datas[0].offset = 0;
datas[0].size = sstride * 240;
datas[0].maxsize = sstride * 240;
datas[0].stride = sstride;
} else {
if (SDL_LockTexture (data->texture, NULL, &ddata, &dstride) < 0) {
@ -267,6 +268,7 @@ alloc_buffers (AppData *data)
b->datas[0].data = ptr;
b->datas[0].offset = 0;
b->datas[0].size = stride * 240;
b->datas[0].maxsize = stride * 240;
b->datas[0].stride = stride;
}
data->n_buffers = MAX_BUFFERS;