From 891805634dac44e7cdb970f318203d0f0fdff8b6 Mon Sep 17 00:00:00 2001 From: Nedko Arnaudov Date: Sun, 2 Jan 2011 04:27:21 +0200 Subject: [PATCH] ladishd: better handling for L1 apps with a2j ports. Fix for #62 --- daemon/app_supervisor.c | 29 ++++++++++++++++++++++++++--- daemon/port.c | 14 +++++++++++++- daemon/port.h | 5 ++++- daemon/virtualizer.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index 6463d63d..d7b3f3e8 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov * ************************************************************************** * 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; } } diff --git a/daemon/port.c b/daemon/port.c index 4590d8ce..6b81ad0a 100644 --- a/daemon/port.c +++ b/daemon/port.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov * ************************************************************************** * 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 diff --git a/daemon/port.h b/daemon/port.h index 264835cf..1eb3e126 100644 --- a/daemon/port.h +++ b/daemon/port.h @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov * ************************************************************************** * 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 */ diff --git a/daemon/virtualizer.c b/daemon/virtualizer.c index 2e956f8a..4c4795f1 100644 --- a/daemon/virtualizer.c +++ b/daemon/virtualizer.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov * ************************************************************************** * 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 */ {