Browse Source

mark clients Finished after process has been called; remove clients that do not respond to events et al; use poll&read to wait for event responses, not just read; add -r to remove/replace JACK SHM registry at startup

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1177 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.115.6
paul 17 years ago
parent
commit
91c1333742
10 changed files with 155 additions and 48 deletions
  1. +1
    -0
      configure.ac
  2. +1
    -0
      jack/engine.h
  3. +1
    -1
      jack/shm.h
  4. +21
    -4
      jackd/clientengine.c
  5. +2
    -0
      jackd/clientengine.h
  6. +86
    -34
      jackd/engine.c
  7. +7
    -0
      jackd/jackd.1.in
  8. +8
    -1
      jackd/jackd.c
  9. +19
    -5
      libjack/client.c
  10. +9
    -3
      libjack/shm.c

+ 1
- 0
configure.ac View File

@@ -789,5 +789,6 @@ echo \| Default driver backend................................ : $JACK_DEFAULT_D
echo \| Shared memory interface............................... : $JACK_SHM_TYPE echo \| Shared memory interface............................... : $JACK_SHM_TYPE
echo \| IPC Temporary directory............................... : $DEFAULT_TMP_DIR echo \| IPC Temporary directory............................... : $DEFAULT_TMP_DIR
echo \| Install prefix........................................ : $prefix echo \| Install prefix........................................ : $prefix
echo \| Default tmp dir....................................... : $DEFAULT_TMP_DIR
echo echo



+ 1
- 0
jack/engine.h View File

@@ -116,6 +116,7 @@ struct _jack_engine {
int reordered; int reordered;
int watchdog_check; int watchdog_check;
int feedbackcount; int feedbackcount;
int removing_clients;
pid_t wait_pid; pid_t wait_pid;
pthread_t freewheel_thread; pthread_t freewheel_thread;
int nozombies; int nozombies;


+ 1
- 1
jack/shm.h View File

@@ -95,7 +95,7 @@ static inline char* jack_shm_addr (jack_shm_info_t* si) {


/* here beginneth the API */ /* here beginneth the API */


extern int jack_register_server (const char *server_name);
extern int jack_register_server (const char *server_name, int new_registry);
extern void jack_unregister_server (const char *server_name); extern void jack_unregister_server (const char *server_name);


extern int jack_initialize_shm (const char *server_name); extern int jack_initialize_shm (const char *server_name);


+ 21
- 4
jackd/clientengine.c View File

@@ -25,6 +25,7 @@


#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <string.h> #include <string.h>


#include <jack/internal.h> #include <jack/internal.h>
@@ -37,8 +38,6 @@
#include "clientengine.h" #include "clientengine.h"
#include "transengine.h" #include "transengine.h"


#define JACK_ERROR_WITH_SOCKETS 10000000

static void static void
jack_client_disconnect_ports (jack_engine_t *engine, jack_client_disconnect_ports (jack_engine_t *engine,
jack_client_internal_t *client) jack_client_internal_t *client)
@@ -68,7 +67,10 @@ jack_client_do_deactivate (jack_engine_t *engine,
jack_client_internal_t *client, int sort_graph) jack_client_internal_t *client, int sort_graph)
{ {
/* caller must hold engine->client_lock and must have checked for and/or /* caller must hold engine->client_lock and must have checked for and/or
* cleared all connections held by client. */
* cleared all connections held by client.
*/
VERBOSE(engine,"+++ deactivate %s", client->control->name);

client->control->active = FALSE; client->control->active = FALSE;


jack_transport_client_exit (engine, client); jack_transport_client_exit (engine, client);
@@ -77,7 +79,7 @@ jack_client_do_deactivate (jack_engine_t *engine,
engine->external_client_cnt > 0) { engine->external_client_cnt > 0) {
engine->external_client_cnt--; engine->external_client_cnt--;
} }
if (sort_graph) { if (sort_graph) {
jack_sort_graph (engine); jack_sort_graph (engine);
} }
@@ -166,6 +168,12 @@ jack_remove_clients (jack_engine_t* engine)
JSList *tmp, *node; JSList *tmp, *node;
int need_sort = FALSE; int need_sort = FALSE;
jack_client_internal_t *client; jack_client_internal_t *client;

if (engine->removing_clients) {
return;
}

engine->removing_clients++;
/* remove all dead clients */ /* remove all dead clients */


@@ -174,6 +182,8 @@ jack_remove_clients (jack_engine_t* engine)
tmp = jack_slist_next (node); tmp = jack_slist_next (node);
client = (jack_client_internal_t *) node->data; client = (jack_client_internal_t *) node->data;

VERBOSE(engine, "client %s error status %d", client->control->name, client->error);
if (client->error) { if (client->error) {
@@ -220,6 +230,8 @@ jack_remove_clients (jack_engine_t* engine)
} }
jack_engine_reset_rolling_usecs (engine); jack_engine_reset_rolling_usecs (engine);

engine->removing_clients--;
} }


static int static int
@@ -848,6 +860,10 @@ jack_client_disconnect (jack_engine_t *engine, int fd)


if (((jack_client_internal_t *) node->data)->request_fd == fd) { if (((jack_client_internal_t *) node->data)->request_fd == fd) {
client = (jack_client_internal_t *) node->data; client = (jack_client_internal_t *) node->data;
VERBOSE (engine, "marking socket error on client %s state = "
"%s errors = %d", client->control->name,
jack_client_state_name (client),
client->error);
if (client->error < JACK_ERROR_WITH_SOCKETS) { if (client->error < JACK_ERROR_WITH_SOCKETS) {
client->error += JACK_ERROR_WITH_SOCKETS; client->error += JACK_ERROR_WITH_SOCKETS;
} }
@@ -961,3 +977,4 @@ jack_intclient_unload_request (jack_engine_t *engine, jack_request_t *req)
req->status = JackFailure; req->status = JackFailure;
} }
} }


+ 2
- 0
jackd/clientengine.h View File

@@ -40,6 +40,8 @@ jack_client_state_name (jack_client_internal_t *client)
return client_state_names[client->control->state]; return client_state_names[client->control->state];
} }


#define JACK_ERROR_WITH_SOCKETS 10000000

int jack_client_activate (jack_engine_t *engine, jack_client_id_t id); int jack_client_activate (jack_engine_t *engine, jack_client_id_t id);
int jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id); int jack_client_deactivate (jack_engine_t *engine, jack_client_id_t id);
int jack_client_create (jack_engine_t *engine, int client_fd); int jack_client_create (jack_engine_t *engine, int client_fd);


+ 86
- 34
jackd/engine.c View File

@@ -1018,8 +1018,9 @@ jack_load_driver (jack_engine_t *engine, jack_driver_desc_t * driver_desc)
void void
jack_driver_unload (jack_driver_t *driver) jack_driver_unload (jack_driver_t *driver)
{ {
void* handle = driver->handle;
driver->finish (driver); driver->finish (driver);
dlclose (driver->handle);
dlclose (handle);
} }


int int
@@ -1471,6 +1472,7 @@ jack_server_thread (void *arg)
} }


if (pfd[i].revents & ~POLLIN) { if (pfd[i].revents & ~POLLIN) {
VERBOSE (engine, "client poll reports non-input condition, fd was %d", pfd[i].fd);
jack_client_disconnect (engine, pfd[i].fd); jack_client_disconnect (engine, pfd[i].fd);
} else if (pfd[i].revents & POLLIN) { } else if (pfd[i].revents & POLLIN) {
if (handle_external_client_request if (handle_external_client_request
@@ -1630,6 +1632,7 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
engine->feedbackcount = 0; engine->feedbackcount = 0;
engine->wait_pid = wait_pid; engine->wait_pid = wait_pid;
engine->nozombies = nozombies; engine->nozombies = nozombies;
engine->removing_clients = 0;


engine->audio_out_cnt = 0; engine->audio_out_cnt = 0;
engine->audio_in_cnt = 0; engine->audio_in_cnt = 0;
@@ -1815,7 +1818,6 @@ jack_engine_new (int realtime, int rtpriority, int do_mlock, int do_unlock,
static void static void
jack_engine_delay (jack_engine_t *engine, float delayed_usecs) jack_engine_delay (jack_engine_t *engine, float delayed_usecs)
{ {
JSList *node;
jack_event_t event; jack_event_t event;
engine->control->frame_timer.reset_pending = 1; engine->control->frame_timer.reset_pending = 1;
@@ -1827,13 +1829,7 @@ jack_engine_delay (jack_engine_t *engine, float delayed_usecs)


event.type = XRun; event.type = XRun;


jack_lock_graph (engine);
for (node = engine->clients; node; node = jack_slist_next (node)) {
jack_deliver_event (engine,
(jack_client_internal_t *) node->data,
&event);
}
jack_unlock_graph (engine);
jack_deliver_event_to_all (engine, &event);
} }


static inline void static inline void
@@ -2265,6 +2261,7 @@ jack_deliver_event_to_all (jack_engine_t *engine, jack_event_t *event)
event); event);
} }
jack_unlock_graph (engine); jack_unlock_graph (engine);
jack_remove_clients (engine);
} }


static void static void
@@ -2307,9 +2304,8 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
our check on a client's continued well-being our check on a client's continued well-being
*/ */


if (client->control->dead
|| (client->control->type == ClientExternal
&& kill (client->control->pid, 0))) {
if (client->control->dead || client->error >= JACK_ERROR_WITH_SOCKETS
|| (client->control->type == ClientExternal && kill (client->control->pid, 0))) {
DEBUG ("client %s is dead - no event sent", DEBUG ("client %s is dead - no event sent",
client->control->name); client->control->name);
return 0; return 0;
@@ -2378,32 +2374,74 @@ jack_deliver_event (jack_engine_t *engine, jack_client_internal_t *client,
jack_error ("cannot send event to client [%s]" jack_error ("cannot send event to client [%s]"
" (%s)", client->control->name, " (%s)", client->control->name,
strerror (errno)); strerror (errno));
client->error++;
}
DEBUG ("engine reading from event fd");
if (!client->error &&
(read (client->event_fd, &status, sizeof (status))
!= sizeof (status))) {
jack_error ("cannot read event response from "
"client [%s] (%s)",
client->control->name,
strerror (errno));
client->error++;
client->error = JACK_ERROR_WITH_SOCKETS+99;
} }


DEBUG ("engine reading from event fd DONE");
if (status != 0) {
jack_error ("bad status for client event "
"handling (type = %d)",
event->type);
client->error++;
}
if (client->error) {
status = 1;
} else {
// then we check whether there really is an error.... :)
struct pollfd pfd[1];
pfd[0].fd = client->event_fd;
//pfd[0].events = POLLERR|POLLIN|POLLHUP|POLLNVAL;
pfd[0].events = POLLIN;
int poll_timeout = (engine->client_timeout_msecs > 0 ?
engine->client_timeout_msecs :
1 + engine->driver->period_usecs/1000);
//poll_timeout = 200;
//poll_timeout = 30000; // 30 seconds
int poll_ret;
// printf("################ poll_timeout = %d (%d or 1 + %d/1000)\n", poll_timeout, engine->client_timeout_msecs, engine->driver->period_usecs);
if ( (poll_ret = poll (pfd, 1, poll_timeout)) < 0) {
DEBUG ("client event poll not ok! (-1) poll returned an error");
jack_error ("poll on subgraph processing failed (%s)", strerror (errno));
status = -1;
} else {
DEBUG ("\n\n\n\n\n back from client event poll, revents = 0x%x\n\n\n", pfd[0].revents);
if (pfd[0].revents & ~POLLIN) {
DEBUG ("client event poll not ok! (-2), revents = %d\n", pfd[0].revents);
jack_error ("subgraph starting at %s lost client", client->control->name);
status = -2;
}
if (pfd[0].revents & POLLIN) {
DEBUG ("client event poll ok!");
status = 0;
} else {
DEBUG ("client event poll not ok! (1 = poll timed out, revents = 0x%04x, poll_ret = %d)", pfd[0].revents, poll_ret);
jack_error ("subgraph starting at %s timed out "
"(subgraph_wait_fd=%d, status = %d, state = %s, revents = 0x%04x)",
client->control->name,
client->subgraph_wait_fd, status,
jack_client_state_name (client), pfd[0].revents);
status = 1;
}
}
}
if (status == 0) {
if (read (client->event_fd, &status, sizeof (status)) != sizeof (status)) {
jack_error ("cannot read event response from "
"client [%s] (%s)",
client->control->name,
strerror (errno));
client->error = JACK_ERROR_WITH_SOCKETS+99;
}
} else {
jack_error ("bad status (%d) for client event "
"handling (type = %d)",
status,event->type);
client->error = JACK_ERROR_WITH_SOCKETS+99;
}
} }
} }

DEBUG ("event delivered"); DEBUG ("event delivered");


return 0; return 0;
@@ -2431,6 +2469,10 @@ jack_rechain_graph (jack_engine_t *engine)


next = jack_slist_next (node); next = jack_slist_next (node);


VERBOSE(engine, "+++ client is now %s active ? %d",
((jack_client_internal_t *) node->data)->control->name,
((jack_client_internal_t *) node->data)->control->active);

if (((jack_client_internal_t *) node->data)->control->active) { if (((jack_client_internal_t *) node->data)->control->active) {


client = (jack_client_internal_t *) node->data; client = (jack_client_internal_t *) node->data;
@@ -2560,6 +2602,8 @@ jack_rechain_graph (jack_engine_t *engine)
subgraph_client->subgraph_wait_fd, n); subgraph_client->subgraph_wait_fd, n);
} }


jack_remove_clients (engine);

VERBOSE (engine, "-- jack_rechain_graph()"); VERBOSE (engine, "-- jack_rechain_graph()");


return err; return err;
@@ -3161,6 +3205,8 @@ jack_port_do_connect (jack_engine_t *engine,
} }


jack_unlock_graph (engine); jack_unlock_graph (engine);
jack_remove_clients (engine);

return 0; return 0;
} }


@@ -3262,6 +3308,8 @@ jack_port_disconnect_internal (jack_engine_t *engine,
} }
} }


jack_remove_clients (engine);

if (check_acyclic) { if (check_acyclic) {
jack_check_acyclic (engine); jack_check_acyclic (engine);
} }
@@ -3785,6 +3833,8 @@ jack_port_registration_notify (jack_engine_t *engine,
} }
} }
} }

jack_remove_clients (engine);
} }


void void
@@ -3820,6 +3870,8 @@ jack_client_registration_notify (jack_engine_t *engine,
} }
} }
} }

jack_remove_clients (engine);
} }


int int


+ 7
- 0
jackd/jackd.1.in View File

@@ -58,6 +58,13 @@ variable. It will be "default" if that is not defined.
Set the maximum number of ports the JACK server can manage. Set the maximum number of ports the JACK server can manage.
The default value is 256. The default value is 256.
.TP .TP
\fB\-r, \-\-replace-registry\fR
.br
Remove the shared memory registry used by all JACK server instances
before startup. This should rarely be used, and is intended only
for occasions when the structure of this registry changes in ways
that are incompatible across JACK versions (which is rare).
.TP
\fB\-R, \-\-realtime\fR \fB\-R, \-\-realtime\fR
.br .br
Use realtime scheduling. This is needed for reliable low\-latency Use realtime scheduling. This is needed for reliable low\-latency


+ 8
- 1
jackd/jackd.c View File

@@ -371,6 +371,7 @@ static void usage (FILE *file)
" [ --debug-timer OR -D ]\n" " [ --debug-timer OR -D ]\n"
" [ --verbose OR -v ]\n" " [ --verbose OR -v ]\n"
" [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n" " [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
" [ --replace-registry OR -r ]\n"
" [ --silent OR -s ]\n" " [ --silent OR -s ]\n"
" [ --version OR -V ]\n" " [ --version OR -V ]\n"
" [ --nozombies OR -Z ]\n" " [ --nozombies OR -Z ]\n"
@@ -520,6 +521,7 @@ main (int argc, char *argv[])
{ "name", 1, 0, 'n' }, { "name", 1, 0, 'n' },
{ "unlock", 0, 0, 'u' }, { "unlock", 0, 0, 'u' },
{ "realtime", 0, 0, 'R' }, { "realtime", 0, 0, 'R' },
{ "replace-registry", 0, 0, 'r' },
{ "realtime-priority", 1, 0, 'P' }, { "realtime-priority", 1, 0, 'P' },
{ "timeout", 1, 0, 't' }, { "timeout", 1, 0, 't' },
{ "temporary", 0, 0, 'T' }, { "temporary", 0, 0, 'T' },
@@ -537,6 +539,7 @@ main (int argc, char *argv[])
JSList * driver_params; JSList * driver_params;
int driver_nargs = 1; int driver_nargs = 1;
int show_version = 0; int show_version = 0;
int replace_registry = 0;
int i; int i;
int rc; int rc;


@@ -593,6 +596,10 @@ main (int argc, char *argv[])
realtime_priority = atoi (optarg); realtime_priority = atoi (optarg);
break; break;


case 'r':
replace_registry = 1;
break;

case 'R': case 'R':
realtime = 1; realtime = 1;
break; break;
@@ -695,7 +702,7 @@ main (int argc, char *argv[])


copyright (stdout); copyright (stdout);


rc = jack_register_server (server_name);
rc = jack_register_server (server_name, replace_registry);
switch (rc) { switch (rc) {
case EEXIST: case EEXIST:
fprintf (stderr, "`%s' server already active\n", server_name); fprintf (stderr, "`%s' server already active\n", server_name);


+ 19
- 5
libjack/client.c View File

@@ -1301,6 +1301,8 @@ jack_client_process_events (jack_client_t* client)
JSList *node; JSList *node;
jack_port_t* port; jack_port_t* port;


DEBUG ("process events");

if (client->pollfd[EVENT_POLL_INDEX].revents & POLLIN) { if (client->pollfd[EVENT_POLL_INDEX].revents & POLLIN) {
DEBUG ("client receives an event, " DEBUG ("client receives an event, "
@@ -1683,14 +1685,26 @@ jack_client_thread_aux (void *arg)
/* wait for first wakeup from server */ /* wait for first wakeup from server */


if (jack_thread_first_wait (client) == control->nframes) { if (jack_thread_first_wait (client) == control->nframes) {

/* now run till we're done */ /* now run till we're done */

if (control->process) { if (control->process) {

/* run process callback, then wait... ad-infinitum */ /* run process callback, then wait... ad-infinitum */
while (jack_thread_wait (client,
control->process (control->nframes,
control->process_arg)) ==
control->nframes)
;

while (1) {
DEBUG("client calls process()");
int status = (control->process (control->nframes,
control->process_arg) ==
control->nframes);
control->state = Finished;
DEBUG("client leaves process(), re-enters wait");
if (!jack_thread_wait (client, status)) {
break;
}
DEBUG("client done with wait");
}

} else { } else {
/* no process handling but still need to process events */ /* no process handling but still need to process events */
while (jack_thread_wait (client, 0) == control->nframes) while (jack_thread_wait (client, 0) == control->nframes)


+ 9
- 3
libjack/shm.c View File

@@ -243,7 +243,7 @@ jack_set_server_prefix (const char *server_name)
* returns: 0 if successful * returns: 0 if successful
*/ */
static int static int
jack_server_initialize_shm (void)
jack_server_initialize_shm (int new_registry)
{ {
int rc; int rc;


@@ -254,6 +254,11 @@ jack_server_initialize_shm (void)


rc = jack_access_registry (&registry_info); rc = jack_access_registry (&registry_info);


if (new_registry) {
jack_remove_shm (&registry_id);
rc = ENOENT;
}

switch (rc) { switch (rc) {
case ENOENT: /* registry does not exist */ case ENOENT: /* registry does not exist */
rc = jack_create_registry (&registry_info); rc = jack_create_registry (&registry_info);
@@ -302,6 +307,7 @@ jack_initialize_shm (const char *server_name)
jack_set_server_prefix (server_name); jack_set_server_prefix (server_name);


jack_shm_lock_registry (); jack_shm_lock_registry ();

if ((rc = jack_access_registry (&registry_info)) == 0) { if ((rc = jack_access_registry (&registry_info)) == 0) {
if ((rc = jack_shm_validate_registry ()) != 0) { if ((rc = jack_shm_validate_registry ()) != 0) {
jack_error ("Incompatible shm registry, " jack_error ("Incompatible shm registry, "
@@ -373,7 +379,7 @@ jack_release_shm_info (jack_shm_registry_index_t index)
* ENOMEM if unable to access shared memory registry * ENOMEM if unable to access shared memory registry
*/ */
int int
jack_register_server (const char *server_name)
jack_register_server (const char *server_name, int new_registry)
{ {
int i; int i;
pid_t my_pid = getpid (); pid_t my_pid = getpid ();
@@ -382,7 +388,7 @@ jack_register_server (const char *server_name)


jack_info ("JACK compiled with %s SHM support.", JACK_SHM_TYPE); jack_info ("JACK compiled with %s SHM support.", JACK_SHM_TYPE);


if (jack_server_initialize_shm ())
if (jack_server_initialize_shm (new_registry))
return ENOMEM; return ENOMEM;


jack_shm_lock_registry (); jack_shm_lock_registry ();


Loading…
Cancel
Save