Browse Source

[0.99.25] fix for port memory leakage

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@829 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.109.0
joq 21 years ago
parent
commit
715c2be22c
4 changed files with 97 additions and 32 deletions
  1. +7
    -0
      jack/internal.h
  2. +52
    -26
      libjack/client.c
  3. +1
    -0
      libjack/local.h
  4. +37
    -6
      libjack/port.c

+ 7
- 0
jack/internal.h View File

@@ -414,5 +414,12 @@ extern char *jack_default_server_name (void);

void silent_jack_error_callback (const char *desc);

/* needed for port management */
jack_port_t *jack_port_by_id_int (const jack_client_t *client,
jack_port_id_t id, int* free);

jack_port_t *jack_port_by_name_int (jack_client_t *client,
const char *port_name);

#endif /* __jack_internal_h__ */


+ 52
- 26
libjack/client.c View File

@@ -160,6 +160,7 @@ jack_client_alloc ()
client->graph_wait_fd = -1;
client->graph_next_fd = -1;
client->ports = NULL;
client->ports_ext = NULL;
client->engine = NULL;
client->control = NULL;
client->thread_ok = FALSE;
@@ -229,32 +230,44 @@ jack_client_invalidate_port_buffers (jack_client_t *client)

int
jack_client_handle_port_connection (jack_client_t *client, jack_event_t *event)

{
jack_port_t *control_port;
jack_port_t *other;
JSList *node;
int need_free = FALSE;

switch (event->type) {
case PortConnected:
other = jack_port_new (client, event->y.other_id, client->engine);
control_port = jack_port_by_id (client, event->x.self_id);
other = jack_port_new (client, event->y.other_id,
client->engine);
/* jack_port_by_id_int() always returns an internal
* port that does not need to be deallocated */
control_port = jack_port_by_id_int (client, event->x.self_id,
&need_free);
pthread_mutex_lock (&control_port->connection_lock);
control_port->connections = jack_slist_prepend (control_port->connections, (void*)other);
control_port->connections =
jack_slist_prepend (control_port->connections,
(void *) other);
pthread_mutex_unlock (&control_port->connection_lock);
break;

case PortDisconnected:
control_port = jack_port_by_id (client, event->x.self_id);

/* jack_port_by_id_int() always returns an internal
* port that does not need to be deallocated */
control_port = jack_port_by_id_int (client, event->x.self_id,
&need_free);
pthread_mutex_lock (&control_port->connection_lock);

for (node = control_port->connections; node; node = jack_slist_next (node)) {
for (node = control_port->connections; node;
node = jack_slist_next (node)) {

other = (jack_port_t *) node->data;

if (other->shared->id == event->y.other_id) {
control_port->connections = jack_slist_remove_link (control_port->connections, node);
control_port->connections =
jack_slist_remove_link (
control_port->connections,
node);
jack_slist_free_1 (node);
free (other);
break;
@@ -439,8 +452,8 @@ _start_server (void)
good = 1;
}
}

if (!good) {
#define JACK_LOCATION
#if defined(USE_CAPABILITIES)
command = JACK_LOCATION "/jackstart";
strncpy(arguments, JACK_LOCATION "/jackstart -T -R -d "
@@ -1006,11 +1019,13 @@ jack_stop_freewheel (jack_client_t* client)

if (client->engine->real_time) {
#if JACK_USE_MACH_THREADS
jack_acquire_real_time_scheduling (client->process_thread,
client->engine->client_priority);
jack_acquire_real_time_scheduling (
client->process_thread,
client->engine->client_priority);
#else
jack_acquire_real_time_scheduling (client->thread,
client->engine->client_priority);
jack_acquire_real_time_scheduling (
client->thread,
client->engine->client_priority);
#endif
}
}
@@ -1070,7 +1085,8 @@ jack_client_thread (void *arg)
* process() cycle.
*/

if (client->graph_wait_fd >= 0 && client->pollfd[WAIT_POLL_INDEX].revents & POLLIN) {
if (client->graph_wait_fd >= 0
&& client->pollfd[WAIT_POLL_INDEX].revents & POLLIN) {
control->awake_at = jack_get_microseconds();
}

@@ -1083,7 +1099,8 @@ jack_client_thread (void *arg)
if (client->graph_wait_fd >= 0 &&
(client->pollfd[WAIT_POLL_INDEX].revents & ~POLLIN)) {
DEBUG ("\n\n\n\n\n\n\n\nWAITFD ERROR, ZOMBIE\n\n\n\n\n");
DEBUG ("\n\n\n\n\n\n\n\nWAITFD ERROR,"
" ZOMBIE\n\n\n\n\n");
/* our upstream "wait" connection
closed, which either means that
@@ -1363,7 +1380,7 @@ jack_client_process_thread (void *arg)
while (err == 0) {
if (jack_client_suspend(client) < 0) {
jack_error ("jack_client_process_thread : resume error");
jack_error ("jack_client_process_thread :resume error");
goto zombie;
}
@@ -1393,13 +1410,16 @@ jack_client_process_thread (void *arg)
#ifdef WITH_TIMESTAMPS
jack_timestamp ("finished");
#endif
DEBUG ("client finished processing at %Lu (elapsed = %f usecs)",
control->finished_at, ((float)(control->finished_at - control->awake_at)));
DEBUG ("client finished processing at %Lu (elapsed = %f usecs)",
control->finished_at,
((float)(control->finished_at - control->awake_at)));
/* check if we were killed during the process cycle (or whatever) */
/* check if we were killed during the process cycle
* (or whatever) */

if (client->control->dead) {
jack_error ("jack_client_process_thread : client->control->dead");
jack_error ("jack_client_process_thread: "
"client->control->dead");
goto zombie;
}

@@ -1420,7 +1440,9 @@ jack_client_process_thread (void *arg)
client->on_shutdown (client->on_shutdown_arg);
} else {
jack_error ("zombified - exiting from JACK");
jack_client_close (client); /* Need a fix : possibly make client crash if zombified without shutdown handler */
/* Need a fix : possibly make client crash if
* zombified without shutdown handler */
jack_client_close (client);
}

pthread_exit (0);
@@ -1436,10 +1458,10 @@ jack_start_thread (jack_client_t *client)
if (client->engine->real_time) {

#ifdef USE_MLOCK
if (client->engine->do_mlock
&& (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) {
jack_error ("cannot lock down memory for RT thread (%s)",
strerror (errno));
if (client->engine->do_mlock
&& (mlockall (MCL_CURRENT | MCL_FUTURE) != 0)) {
jack_error ("cannot lock down memory for RT thread "
"(%s)", strerror (errno));
#ifdef ENSURE_MLOCK
return -1;
@@ -1569,7 +1591,7 @@ jack_activate (jack_client_t *client)

pthread_cond_wait (&client_ready, &client_lock);
pthread_mutex_unlock (&client_lock);
if (!client->thread_ok) {
jack_error ("could not start client thread");
return -1;
@@ -1663,6 +1685,10 @@ jack_client_close (jack_client_t *client)
free (node->data);
}
jack_slist_free (client->ports);
for (node = client->ports_ext; node; node = jack_slist_next (node)) {
free (node->data);
}
jack_slist_free (client->ports_ext);
jack_client_free (client);

return 0;


+ 1
- 0
libjack/local.h View File

@@ -23,6 +23,7 @@ struct _jack_client {
jack_shm_info_t* port_segment;

JSList *ports;
JSList *ports_ext;

pthread_t thread;
char fifo_prefix[PATH_MAX+1];


+ 37
- 6
libjack/port.c View File

@@ -98,7 +98,8 @@ jack_port_new (const jack_client_t *client, jack_port_id_t port_id,
are changed.
*/

port->client_segment_base = (void **) &client->port_segment[ptid].attached_at;
port->client_segment_base =
(void **) &client->port_segment[ptid].attached_at;
return port;
}
@@ -262,7 +263,9 @@ jack_port_get_all_connections (const jack_client_t *client,
{
const char **ret;
jack_request_t req;
jack_port_t *tmp;
unsigned int i;
int need_free = FALSE;

if (port == NULL) {
return NULL;
@@ -299,8 +302,12 @@ jack_port_get_all_connections (const jack_client_t *client,
jack_error ("cannot read port id from server");
return 0;
}
ret[i] = jack_port_by_id (client, port_id)->shared->name;
tmp = jack_port_by_id_int (client, port_id, &need_free);
ret[i] = tmp->shared->name;
if (need_free) {
free (tmp);
need_free = FALSE;
}
}

ret[i] = NULL;
@@ -309,12 +316,13 @@ jack_port_get_all_connections (const jack_client_t *client,
}

jack_port_t *
jack_port_by_id (const jack_client_t *client, jack_port_id_t id)
jack_port_by_id_int (const jack_client_t *client, jack_port_id_t id, int* free)
{
JSList *node;

for (node = client->ports; node; node = jack_slist_next (node)) {
if (((jack_port_t *) node->data)->shared->id == id) {
*free = FALSE;
return (jack_port_t *) node->data;
}
}
@@ -322,14 +330,27 @@ jack_port_by_id (const jack_client_t *client, jack_port_id_t id)
if (id >= client->engine->port_max)
return NULL;

if (client->engine->ports[id].in_use)
if (client->engine->ports[id].in_use) {
*free = TRUE;
return jack_port_new (client, id, client->engine);
}

return NULL;
}

jack_port_t *
jack_port_by_name (jack_client_t *client, const char *port_name)
jack_port_by_id (const jack_client_t *client, jack_port_id_t id)
{
int need_free = FALSE;
jack_port_t * port = jack_port_by_id_int (client,id,&need_free);
if (port != NULL && need_free)
client->ports_ext =
jack_slist_prepend (client->ports_ext, port);
return port;
}

jack_port_t *
jack_port_by_name_int (jack_client_t *client, const char *port_name)
{
unsigned long i, limit;
jack_port_shared_t *port;
@@ -347,6 +368,16 @@ jack_port_by_name (jack_client_t *client, const char *port_name)
return NULL;
}

jack_port_t *
jack_port_by_name (jack_client_t *client, const char *port_name)
{
jack_port_t * port = jack_port_by_name_int (client, port_name);
if (port != NULL)
client->ports_ext =
jack_slist_prepend (client->ports_ext, port);
return port;
}

jack_nframes_t
jack_port_get_latency (jack_port_t *port)
{


Loading…
Cancel
Save