Detect the silent death of the jack client thread.

When jackd gets an unhandled xrun, it stops all processing but neglects to
tell the client about it. Thus, add a bit of a watchdog function to
s_update() and assume the client thread is dead if there's no sign of life
after one second. No more hanging on exit.
This commit is contained in:
Bill Currie 2011-09-07 15:13:47 +09:00
parent 86c5b79816
commit 9ffa1f410a
2 changed files with 56 additions and 12 deletions

10
TODO
View file

@ -14,28 +14,30 @@ X ~/.quakeforgerc should support all commands, not just set and setrom
X software PCXs don't work in X11 at least if you're using 16/24/32 color X software PCXs don't work in X11 at least if you're using 16/24/32 color
X ogg support X ogg support
X server-side demos X server-side demos
X Scitech MGL used in win32 is screwed - dump it and use SDL
X kill MAX_STATIC_ENTITIES
X stateful console (eg, rcon mode, chat mode, normal command mode...)
M it seems possible to crash a QF server still - need to fix this! M it seems possible to crash a QF server still - need to fix this!
M merge nq and qw code bases M merge nq and qw code bases
M mingw cross compiling M mingw cross compiling
X Scitech MGL used in win32 is screwed - dump it and use SDL
M software targets should mix color at 16/16 or 24/32 color M software targets should mix color at 16/16 or 24/32 color
I GL is still way too slow I GL is still way too slow
I Client side QuakeC. I Client side QuakeC.
I menu rewrite I menu rewrite
I clean up TODO ;) I clean up TODO ;)
o kill MAX_STATIC_ENTITIES
o doublesize modes (eg, render in 320x240 but display in 640x480) o doublesize modes (eg, render in 320x240 but display in 640x480)
o allow qf clients to download .lit files from qf servers. o allow qf clients to download .lit files from qf servers.
o better server control of certain cvars o better server control of certain cvars
o triggers (f_respawn, f_death, f_took; cl_triggers) o triggers (f_respawn, f_death, f_took; cl_triggers)
X stateful console (eg, rcon mode, chat mode, normal command mode...)
o scripted hud o scripted hud
o add a U_PHYSICAL field to entities. it should include a solid bit, o add a U_PHYSICAL field to entities. it should include a solid bit,
a rotated bbox bit, and mins/maxs for the bbos a rotated bbox bit, and mins/maxs for the bbos
o gui for serverlist o gui for serverlist
o add favorates serverlist manipulation o add favorites serverlist manipulation
o redo serverlist filtering for better flexability and/or easier use o redo serverlist filtering for better flexability and/or easier use
o add individual server ping/info request from console o add individual server ping/info request from console
? dynamically allocate missing fields, particularly ones not needed by the
progs.
? more direct intra-team comms (eg, talk to offense or defense directly) ? more direct intra-team comms (eg, talk to offense or defense directly)
? Draw_Pic and friends need a cleanup in GL at least ? Draw_Pic and friends need a cleanup in GL at least
? Draw_Pic and other tex draw functions should use local palettes ? Draw_Pic and other tex draw functions should use local palettes

View file

@ -53,6 +53,8 @@ static __attribute__ ((used)) const char rcsid[] =
static int sound_started = 0; static int sound_started = 0;
static int snd_blocked = 0; static int snd_blocked = 0;
static int snd_shutdown = 0; static int snd_shutdown = 0;
static int snd_alive = 0;
static double snd_alive_time = 0;
static jack_client_t *jack_handle; static jack_client_t *jack_handle;
static jack_port_t *jack_out[2]; static jack_port_t *jack_out[2];
static dma_t _snd_shm; static dma_t _snd_shm;
@ -78,12 +80,38 @@ s_start_sound (int entnum, int entchannel, sfx_t *sfx, const vec3_t origin,
SND_StartSound (entnum, entchannel, sfx, origin, fvol, attenuation); SND_StartSound (entnum, entchannel, sfx, origin, fvol, attenuation);
} }
static void
s_finish_channels (void)
{
int i;
channel_t *ch;
for (i = 0; i < MAX_CHANNELS; i++) {
ch = &snd_channels[i];
ch->done = ch->stop = 1;
}
}
static void static void
s_update (const vec3_t origin, const vec3_t forward, const vec3_t right, s_update (const vec3_t origin, const vec3_t forward, const vec3_t right,
const vec3_t up) const vec3_t up)
{ {
double now = Sys_DoubleTime ();
if (!sound_started) if (!sound_started)
return; return;
if (snd_alive) {
snd_alive = 0;
snd_alive_time = now;
} else {
if (!snd_shutdown) {
if (now - snd_alive_time > 1.0) {
Sys_Printf ("jackd client thread seems to have died\n");
s_finish_channels ();
snd_shutdown = 1;
}
}
}
if (snd_shutdown) { if (snd_shutdown) {
if (snd_shutdown == 1) { if (snd_shutdown == 1) {
snd_shutdown++; snd_shutdown++;
@ -120,8 +148,10 @@ s_jack_activate (void)
} }
ports = jack_get_ports (jack_handle, 0, 0, ports = jack_get_ports (jack_handle, 0, 0,
JackPortIsPhysical | JackPortIsInput); JackPortIsPhysical | JackPortIsInput);
//for (i = 0; ports[i]; i++) if (developer->int_val & SYS_SND) {
// Sys_Printf ("%s\n", ports[i]); for (i = 0; ports[i]; i++)
Sys_Printf ("%s\n", ports[i]);
}
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
jack_connect (jack_handle, jack_port_name (jack_out[i]), ports[i]); jack_connect (jack_handle, jack_port_name (jack_out[i]), ports[i]);
free (ports); free (ports);
@ -254,6 +284,7 @@ snd_jack_process (jack_nframes_t nframes, void *arg)
{ {
int i; int i;
snd_alive = 1;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes); output[i] = (float *) jack_port_get_buffer (jack_out[i], nframes);
SND_PaintChannels (snd_paintedtime + nframes); SND_PaintChannels (snd_paintedtime + nframes);
@ -263,13 +294,21 @@ snd_jack_process (jack_nframes_t nframes, void *arg)
static void static void
snd_jack_shutdown (void *arg) snd_jack_shutdown (void *arg)
{ {
int i;
channel_t *ch;
snd_shutdown = 1; snd_shutdown = 1;
for (i = 0; i < MAX_CHANNELS; i++) { s_finish_channels ();
ch = &snd_channels[i];
ch->done = ch->stop = 1;
} }
static void
snd_jack_error (const char *desc)
{
fprintf (stderr, "snd_jack: %s\n", desc);
}
static int
snd_jack_xrun (void *arg)
{
fprintf (stderr, "snd_jack: xrun\n");
return 0;
} }
static void static void
@ -291,12 +330,15 @@ s_init (void)
SND_SFX_Init (); SND_SFX_Init ();
SND_Channels_Init (); SND_Channels_Init ();
jack_set_error_function (snd_jack_error);
if ((jack_handle = jack_client_open ("QuakeForge", if ((jack_handle = jack_client_open ("QuakeForge",
JackServerName | JackNoStartServer, 0, JackServerName | JackNoStartServer, 0,
snd_jack_server->string)) == 0) { snd_jack_server->string)) == 0) {
Sys_Printf ("Could not connect to JACK\n"); Sys_Printf ("Could not connect to JACK\n");
return; return;
} }
if (jack_set_xrun_callback (jack_handle, snd_jack_xrun, 0))
Sys_Printf ("Could not set xrun callback\n");
jack_set_process_callback (jack_handle, snd_jack_process, 0); jack_set_process_callback (jack_handle, snd_jack_process, 0);
jack_on_shutdown (jack_handle, snd_jack_shutdown, 0); jack_on_shutdown (jack_handle, snd_jack_shutdown, 0);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)