ladishd: better handling for L1 apps with a2j ports. Fix for #62

This commit is contained in:
Nedko Arnaudov 2011-01-02 04:27:21 +02:00
parent d65ebbbf5b
commit 891805634d
4 changed files with 75 additions and 6 deletions

View File

@ -2,7 +2,7 @@
/*
* LADI Session Handler (ladish)
*
* Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
* Copyright (C) 2009, 2010, 2011 Nedko Arnaudov <nedko@arnaudov.name>
*
**************************************************************************
* This file contains implementation of app supervisor object
@ -50,6 +50,7 @@ struct ladish_app
pid_t pgrp;
pid_t firstborn_pid;
pid_t firstborn_pgrp;
int firstborn_refcount;
bool zombie; /* if true, remove when stopped */
bool autorun;
unsigned int state;
@ -288,6 +289,7 @@ ladish_app_supervisor_add(
app_ptr->pgrp = 0;
app_ptr->firstborn_pid = 0;
app_ptr->firstborn_pgrp = 0;
app_ptr->firstborn_refcount = 0;
app_ptr->id = supervisor_ptr->next_id++;
if (uuid == NULL || uuid_is_null(uuid))
@ -349,6 +351,13 @@ static void ladish_app_send_signal(struct ladish_app * app_ptr, int sig, bool pr
}
}
if (app_ptr->pid == 0)
{
log_error("not sending signal %d (%s) to app '%s' because its pid is %d", sig, signal_name, app_ptr->name, (int)app_ptr->pid);
ASSERT_NO_PASS;
return;
}
switch (sig)
{
case SIGKILL:
@ -553,8 +562,9 @@ bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_ha
app_ptr->pid = 0;
app_ptr->pgrp = 0;
app_ptr->firstborn_pid = 0;
app_ptr->firstborn_pgrp = 0;
/* firstborn pid and pgrp is not reset here because it is refcounted
and managed independently through the add/del_pid() methods */
if (app_ptr->zombie)
{
remove_app_internal(supervisor_ptr, app_ptr);
@ -700,20 +710,33 @@ void ladish_app_add_pid(ladish_app_handle app_handle, pid_t pid)
if (app_ptr->firstborn_pid != 0)
{ /* Ignore non-first children */
if (app_ptr->firstborn_pid == pid)
{
app_ptr->firstborn_refcount++;
}
return;
}
log_info("First grandchild with pid %u", (unsigned int)pid);
app_ptr->firstborn_pid = pid;
ASSERT(app_ptr->firstborn_refcount == 0);
app_ptr->firstborn_refcount = 1;
}
void ladish_app_del_pid(ladish_app_handle app_handle, pid_t pid)
{
if (app_ptr->firstborn_pid != 0 && app_ptr->firstborn_pid == pid)
{
ASSERT(app_ptr->firstborn_refcount > 0);
app_ptr->firstborn_refcount--;
if (app_ptr->firstborn_refcount > 0)
{
return;
}
log_info("First grandchild with pid %u has gone", (unsigned int)pid);
app_ptr->firstborn_pid = 0;
app_ptr->firstborn_pgrp = 0;
app_ptr->firstborn_refcount = 0;
}
}

View File

@ -2,7 +2,7 @@
/*
* LADI Session Handler (ladish)
*
* Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
* Copyright (C) 2009, 2010, 2011 Nedko Arnaudov <nedko@arnaudov.name>
*
**************************************************************************
* This file contains the implementation of the port objects
@ -36,6 +36,8 @@ struct ladish_port
uint64_t jack_id; /* JACK port ID. */
uint64_t jack_id_room; /* JACK port ID in room. valid only for link ports */
pid_t pid; /* process id. */
void * vgraph; /* virtual graph */
ladish_dict_handle dict;
@ -203,4 +205,14 @@ bool ladish_port_belongs_to_app(ladish_port_handle port_handle, const uuid_t app
return uuid_compare(port_ptr->app_uuid, app_uuid) == 0;
}
void ladish_port_set_pid(ladish_port_handle port_handle, pid_t pid)
{
port_ptr->pid = pid;
}
pid_t ladish_port_get_pid(ladish_port_handle port_handle)
{
return port_ptr->pid;
}
#undef port_ptr

View File

@ -2,7 +2,7 @@
/*
* LADI Session Handler (ladish)
*
* Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
* Copyright (C) 2009, 2010, 2011 Nedko Arnaudov <nedko@arnaudov.name>
*
**************************************************************************
* This file contains the interface of the port objects
@ -55,4 +55,7 @@ bool ladish_port_get_app(ladish_port_handle port, uuid_t app_uuid);
bool ladish_port_has_app(ladish_port_handle port);
bool ladish_port_belongs_to_app(ladish_port_handle port, const uuid_t app_uuid);
void ladish_port_set_pid(ladish_port_handle port_handle, pid_t pid);
pid_t ladish_port_get_pid(ladish_port_handle port_handle);
#endif /* #ifndef PORT_H__62F81E7C_91FA_44AB_94A9_E0E2D226ED58__INCLUDED */

View File

@ -2,7 +2,7 @@
/*
* LADI Session Handler (ladish)
*
* Copyright (C) 2009, 2010 Nedko Arnaudov <nedko@arnaudov.name>
* Copyright (C) 2009, 2010, 2011 Nedko Arnaudov <nedko@arnaudov.name>
*
**************************************************************************
* This file contains implementation of the graph virtualizer object
@ -576,6 +576,7 @@ port_appeared(
vclient_name = ladish_app_get_name(app);
has_app = true;
log_info("ALSA app name is '%s'", vclient_name);
ladish_app_add_pid(app, pid);
}
}
else
@ -637,6 +638,7 @@ port_appeared(
if (has_app)
{
ladish_port_set_app(port, app_uuid);
ladish_port_set_pid(port, pid);
if (!ladish_client_has_app(vclient))
{
ladish_client_set_app(vclient, app_uuid);
@ -666,6 +668,7 @@ port_appeared(
if (has_app)
{
ladish_port_set_app(port, app_uuid);
ladish_port_set_pid(port, pid);
}
ladish_dict_set(ladish_port_get_dict(port), URI_A2J_PORT, is_a2j ? "yes" : "no");
@ -825,6 +828,28 @@ exit:
return;
}
static void maybe_clear_a2j_port_pid(ladish_graph_handle vgraph, ladish_client_handle jclient, ladish_port_handle port)
{
const char * opath;
uuid_t app_uuid;
ladish_app_handle app;
ladish_app_supervisor_handle app_supervisor;
pid_t pid;
if (ladish_virtualizer_is_a2j_client(jclient) && ladish_port_get_app(port, app_uuid))
{
pid = ladish_port_get_pid(port);
opath = ladish_graph_get_opath(vgraph);
log_info("releasing reference for pid %d of a2j port in %s", (int)pid, ladish_graph_get_description(vgraph));
app_supervisor = ladish_studio_find_app_supervisor(opath);
app = ladish_app_supervisor_find_app_by_uuid(app_supervisor, app_uuid);
if (app != NULL && pid != 0)
{
ladish_app_del_pid(app, pid);
}
}
}
static void port_disappeared(void * context, uint64_t client_id, uint64_t port_id)
{
ladish_client_handle jclient;
@ -865,6 +890,12 @@ static void port_disappeared(void * context, uint64_t client_id, uint64_t port_i
jmcore = true;
ladish_graph_remove_port_by_jack_id(virtualizer_ptr->jack_graph, port_id, true, true);
}
else
{
maybe_clear_a2j_port_pid(vgraph, jclient, port);
}
ladish_port_set_pid(port, 0);
if (ladish_graph_is_persist(vgraph)) /* if port is supposed to be persisted */
{