diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index ac843d57..8707e45e 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -125,6 +125,8 @@ struct ladish_app * ladish_app_supervisor_find_app_by_id_internal(struct ladish_ void remove_app_internal(struct ladish_app_supervisor * supervisor_ptr, struct ladish_app * app_ptr) { + ASSERT(app_ptr->pid == 0); /* Removing not-stoped app? Zombies will make a rebellion! */ + list_del(&app_ptr->siblings); dbus_signal_emit( @@ -848,7 +850,6 @@ static void set_app_properties(struct dbus_method_call * call_ptr) static void remove_app(struct dbus_method_call * call_ptr) { uint64_t id; - struct ladish_app * app_ptr; if (!dbus_message_get_args( call_ptr->message, @@ -861,25 +862,10 @@ static void remove_app(struct dbus_method_call * call_ptr) return; } - app_ptr = ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr, id); - if (app_ptr == NULL) + if (ladish_command_remove_app(call_ptr, ladish_studio_get_cmd_queue(), supervisor_ptr->opath, id)) { - lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); - return; + method_return_new_void(call_ptr); } - - if (app_ptr->pid != 0) - { - app_ptr->zombie = true; - app_ptr->state = LADISH_APP_STATE_STOPPING; - kill(app_ptr->pid, SIGTERM); - } - else - { - remove_app_internal(supervisor_ptr, app_ptr); - } - - method_return_new_void(call_ptr); } static void is_app_running(struct dbus_method_call * call_ptr) diff --git a/daemon/cmd.h b/daemon/cmd.h index 1a5c74da..c8a6dc80 100644 --- a/daemon/cmd.h +++ b/daemon/cmd.h @@ -81,6 +81,7 @@ ladish_command_new_app( uint8_t level); bool ladish_command_change_app_state(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * opath, uint64_t id, unsigned int target_state); +bool ladish_command_remove_app(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * opath, uint64_t id); bool ladish_command_create_room(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * room_name, const char * template_name); bool ladish_command_delete_room(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * room_name); diff --git a/daemon/cmd_remove_app.c b/daemon/cmd_remove_app.c new file mode 100644 index 00000000..533fcbb6 --- /dev/null +++ b/daemon/cmd_remove_app.c @@ -0,0 +1,143 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains implementation of the "remove app" command + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "cmd.h" +#include "studio.h" +#include "../dbus/error.h" +#include "../proxies/notify_proxy.h" +#include "virtualizer.h" + +struct ladish_command_remove_app +{ + struct ladish_command command; /* must be the first member */ + char * opath; + uint64_t id; +}; + +#define cmd_ptr ((struct ladish_command_remove_app *)context) + +static bool run(void * context) +{ + ladish_app_supervisor_handle supervisor; + ladish_app_handle app; + const char * app_name; + + ASSERT(cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING); + + log_info("remove app command. opath='%s'", cmd_ptr->opath); + + supervisor = ladish_studio_find_app_supervisor(cmd_ptr->opath); + if (supervisor == NULL) + { + log_error("cannot find supervisor '%s' to remove app from", cmd_ptr->opath); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot remove app because of internal error (unknown supervisor)", NULL); + return false; + } + + app = ladish_app_supervisor_find_app_by_id(supervisor, cmd_ptr->id); + if (app == NULL) + { + log_error("App with ID %"PRIu64" not found and (remove)", cmd_ptr->id); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot remove app because it is not found", NULL); + return false; + } + + app_name = ladish_app_get_name(app); + + if (ladish_app_is_running(app)) + { + if (cmd_ptr->command.state == LADISH_COMMAND_STATE_PENDING) + { + log_info("App %s is not stopped as it should", app_name); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "Cannot remove app because it is not stopped (because of internal error)", NULL); + } + return false; + } + + /* remove jclient and vclient for this app */ + log_info("Removing graph objects for app '%s'", app_name); + ladish_virtualizer_remove_app(ladish_studio_get_jack_graph(), app_name); + + ladish_app_supervisor_remove_app(supervisor, app); + cmd_ptr->command.state = LADISH_COMMAND_STATE_DONE; + return true; +} + +static void destructor(void * context) +{ + log_info("remove_app command destructor"); + free(cmd_ptr->opath); +} + +#undef cmd_ptr + +bool ladish_command_remove_app(void * call_ptr, struct ladish_cqueue * queue_ptr, const char * opath, uint64_t id) +{ + struct ladish_command_remove_app * cmd_ptr; + char * opath_dup; + + if (!ladish_command_change_app_state(call_ptr, queue_ptr, opath, id, LADISH_APP_STATE_STOPPED)) + { + goto fail; + } + + opath_dup = strdup(opath); + if (opath_dup == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup('%s') failed.", opath); + goto fail_drop_stop_command; + } + + cmd_ptr = ladish_command_new(sizeof(struct ladish_command_remove_app)); + if (cmd_ptr == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_command_new() failed."); + goto fail_free_opath; + } + + cmd_ptr->command.run = run; + cmd_ptr->command.destructor = destructor; + cmd_ptr->opath = opath_dup; + cmd_ptr->id = id; + + if (!ladish_cqueue_add_command(queue_ptr, &cmd_ptr->command)) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "ladish_cqueue_add_command() failed."); + goto fail_destroy_command; + } + + return true; + +fail_destroy_command: + free(cmd_ptr); +fail_free_opath: + free(opath_dup); +fail_drop_stop_command: + ladish_cqueue_drop_command(queue_ptr); +fail: + return false; +} diff --git a/wscript b/wscript index be2ac16f..6a6848f8 100644 --- a/wscript +++ b/wscript @@ -233,6 +233,7 @@ def build(bld): 'cmd_unload_studio.c', 'cmd_new_app.c', 'cmd_change_app_state.c', + 'cmd_remove_app.c', 'cmd_create_room.c', 'cmd_delete_room.c', 'cmd_exit.c',