From 89461c363c65b93e7d8e76d49fa1695b8b76e257 Mon Sep 17 00:00:00 2001 From: Nedko Arnaudov Date: Fri, 4 Dec 2009 21:37:39 +0200 Subject: [PATCH] app list is now managable from gladish --- daemon/app_supervisor.c | 109 +++++++++++++++++++++++++++++++++++++-------- gui/app_supervisor_proxy.c | 44 ++++++++++++++++++ gui/app_supervisor_proxy.h | 4 ++ gui/graph_view.c | 5 +++ gui/graph_view.h | 2 + gui/world_tree.c | 78 +++++++++++++++++++++++++++----- 6 files changed, 214 insertions(+), 28 deletions(-) diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index 26158372..b6aed720 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -42,6 +42,7 @@ struct ladish_app bool terminal; uint8_t level; pid_t pid; + bool zombie; }; struct ladish_app_supervisor @@ -125,6 +126,45 @@ struct ladish_app * ladish_app_supervisor_find_app_by_id(struct ladish_app_super return NULL; } +void remove_app_internal(struct ladish_app_supervisor * supervisor_ptr, struct ladish_app * app_ptr) +{ + list_del(&app_ptr->siblings); + + dbus_signal_emit( + g_dbus_connection, + supervisor_ptr->opath, + IFACE_APP_SUPERVISOR, + "AppRemoved", + "tt", + &supervisor_ptr->version, + &app_ptr->id); + + free(app_ptr->name); + free(app_ptr->commandline); + free(app_ptr); +} + +void emit_app_state_changed(struct ladish_app_supervisor * supervisor_ptr, struct ladish_app * app_ptr) +{ + dbus_bool_t running; + dbus_bool_t terminal; + + running = app_ptr->pid != 0; + terminal = app_ptr->terminal; + + dbus_signal_emit( + g_dbus_connection, + supervisor_ptr->opath, + IFACE_APP_SUPERVISOR, + "AppStateChanged", + "tsbby", + &app_ptr->id, + &app_ptr->name, + &running, + &terminal, + &app_ptr->level); +} + #define supervisor_ptr ((struct ladish_app_supervisor *)supervisor_handle) void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handle) @@ -134,10 +174,7 @@ void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handl while (!list_empty(&supervisor_ptr->applist)) { app_ptr = list_entry(supervisor_ptr->applist.next, struct ladish_app, siblings); - list_del(&app_ptr->siblings); - free(app_ptr->name); - free(app_ptr->commandline); - free(app_ptr); + remove_app_internal(supervisor_ptr, app_ptr); } free(supervisor_ptr->name); @@ -157,20 +194,16 @@ bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_ha { log_info("exit of studio child '%s' detected.", app_ptr->name); - list_del(&app_ptr->siblings); - - dbus_signal_emit( - g_dbus_connection, - supervisor_ptr->opath, - IFACE_APP_SUPERVISOR, - "AppRemoved", - "tt", - &supervisor_ptr->version, - &app_ptr->id); + app_ptr->pid = 0; + if (app_ptr->zombie) + { + remove_app_internal(supervisor_ptr, app_ptr); + } + else + { + emit_app_state_changed(supervisor_ptr, app_ptr); + } - free(app_ptr->name); - free(app_ptr->commandline); - free(app_ptr); return true; } } @@ -356,6 +389,7 @@ static void run_custom(struct dbus_method_call * call_ptr) app_ptr->id = supervisor_ptr->next_id++; app_ptr->name = name; app_ptr->commandline = strdup(commandline); + app_ptr->terminal = terminal; app_ptr->pid = 0; if (app_ptr->commandline == NULL) { @@ -365,6 +399,7 @@ static void run_custom(struct dbus_method_call * call_ptr) return; } + app_ptr->zombie = false; list_add_tail(&app_ptr->siblings, &supervisor_ptr->applist); if (!loader_execute(supervisor_ptr->name, name, "/", terminal, commandline, &app_ptr->pid)) @@ -427,12 +462,14 @@ static void start_app(struct dbus_method_call * call_ptr) return; } + app_ptr->zombie = false; if (!loader_execute(supervisor_ptr->name, app_ptr->name, "/", app_ptr->terminal, app_ptr->commandline, &app_ptr->pid)) { lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Execution of '%s' failed", app_ptr->commandline); return; } + emit_app_state_changed(supervisor_ptr, app_ptr); log_info("%s pid is %lu", app_ptr->name, (unsigned long)app_ptr->pid); method_return_new_void(call_ptr); @@ -516,6 +553,38 @@ 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, + &g_dbus_error, + DBUS_TYPE_UINT64, &id, + DBUS_TYPE_INVALID)) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "Invalid arguments to method \"%s\": %s", call_ptr->method_name, g_dbus_error.message); + dbus_error_free(&g_dbus_error); + return; + } + + app_ptr = ladish_app_supervisor_find_app_by_id(supervisor_ptr, id); + if (app_ptr == NULL) + { + lash_dbus_error(call_ptr, LASH_DBUS_ERROR_INVALID_ARGS, "App with ID %"PRIu64" not found", id); + return; + } + + if (app_ptr->pid != 0) + { + app_ptr->zombie = true; + 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) @@ -573,6 +642,10 @@ METHOD_ARGS_BEGIN(KillApp, "Kill application") METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app") METHOD_ARGS_END +METHOD_ARGS_BEGIN(RemoveApp, "Remove application") + METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app") +METHOD_ARGS_END + METHOD_ARGS_BEGIN(GetAppProperties, "Get properties of an application") METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING, "id of app") METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING, "") @@ -603,7 +676,7 @@ METHODS_BEGIN METHOD_DESCRIBE(KillApp, kill_app) METHOD_DESCRIBE(GetAppProperties, get_app_properties) METHOD_DESCRIBE(SetAppProperties, set_app_properties) - METHOD_DESCRIBE(KillApp, remove_app) + METHOD_DESCRIBE(RemoveApp, remove_app) METHOD_DESCRIBE(IsAppRunning, is_app_running) METHODS_END diff --git a/gui/app_supervisor_proxy.c b/gui/app_supervisor_proxy.c index e2b1b286..82460482 100644 --- a/gui/app_supervisor_proxy.c +++ b/gui/app_supervisor_proxy.c @@ -316,4 +316,48 @@ bool ladish_app_supervisor_proxy_run_custom(ladish_app_supervisor_proxy_handle p return true; } +bool ladish_app_supervisor_proxy_start_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id) +{ + if (!dbus_call(proxy_ptr->service, proxy_ptr->object, IFACE_APP_SUPERVISOR, "StartApp", "t", &id, "")) + { + log_error("StartApp() failed."); + return false; + } + + return true; +} + +bool ladish_app_supervisor_proxy_stop_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id) +{ + if (!dbus_call(proxy_ptr->service, proxy_ptr->object, IFACE_APP_SUPERVISOR, "StopApp", "t", &id, "")) + { + log_error("StopApp() failed."); + return false; + } + + return true; +} + +bool ladish_app_supervisor_proxy_kill_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id) +{ + if (!dbus_call(proxy_ptr->service, proxy_ptr->object, IFACE_APP_SUPERVISOR, "KillApp", "t", &id, "")) + { + log_error("KillApp() failed."); + return false; + } + + return true; +} + +bool ladish_app_supervisor_proxy_remove_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id) +{ + if (!dbus_call(proxy_ptr->service, proxy_ptr->object, IFACE_APP_SUPERVISOR, "RemoveApp", "t", &id, "")) + { + log_error("RemoveApp() failed."); + return false; + } + + return true; +} + #undef proxy_ptr diff --git a/gui/app_supervisor_proxy.h b/gui/app_supervisor_proxy.h index 61dad9d2..6e8faaba 100644 --- a/gui/app_supervisor_proxy.h +++ b/gui/app_supervisor_proxy.h @@ -43,5 +43,9 @@ ladish_app_supervisor_proxy_create( void ladish_app_supervisor_proxy_destroy(ladish_app_supervisor_proxy_handle proxy); bool ladish_app_supervisor_proxy_run_custom(ladish_app_supervisor_proxy_handle proxy, const char * command, const char * name, bool run_in_terminal); +bool ladish_app_supervisor_proxy_start_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id); +bool ladish_app_supervisor_proxy_stop_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id); +bool ladish_app_supervisor_proxy_kill_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id); +bool ladish_app_supervisor_proxy_remove_app(ladish_app_supervisor_proxy_handle proxy, uint64_t id); #endif /* #ifndef APP_SUPERVISOR_PROXY_H__A48C609D_0AB6_4C91_A9B0_BC7F1B7E4CB4__INCLUDED */ diff --git a/gui/graph_view.c b/gui/graph_view.c index 1be7bf0c..7b951c11 100644 --- a/gui/graph_view.c +++ b/gui/graph_view.c @@ -272,3 +272,8 @@ bool app_run_custom(graph_view_handle view, const char * command, const char * n { return ladish_app_supervisor_proxy_run_custom(view_ptr->app_supervisor, command, name, run_in_terminal); } + +ladish_app_supervisor_proxy_handle graph_view_get_app_supervisor(graph_view_handle view) +{ + return view_ptr->app_supervisor; +} diff --git a/gui/graph_view.h b/gui/graph_view.h index 3b613ee2..a05c2d44 100644 --- a/gui/graph_view.h +++ b/gui/graph_view.h @@ -28,6 +28,7 @@ #define GRAPH_VIEW_H__05B5CE46_5239_43F1_9F31_79F13EBF0DFA__INCLUDED #include "graph_canvas.h" +#include "app_supervisor_proxy.h" typedef struct graph_view_tag { int unused; } * graph_view_handle; @@ -49,6 +50,7 @@ const char * get_view_name(graph_view_handle view); bool set_view_name(graph_view_handle view, const char * name); canvas_handle get_current_canvas(); +ladish_app_supervisor_proxy_handle graph_view_get_app_supervisor(graph_view_handle view); bool app_run_custom(graph_view_handle view, const char * command, const char * name, bool run_in_terminal); /* not very good place for this prototype, because it is not implemented in graph_view.c */ diff --git a/gui/world_tree.c b/gui/world_tree.c index 112c06ac..53b784c1 100644 --- a/gui/world_tree.c +++ b/gui/world_tree.c @@ -79,22 +79,24 @@ on_select( return TRUE; } -bool get_selected_app_id(uint64_t * id_ptr) +bool get_selected_app_id(graph_view_handle * view_ptr, uint64_t * id_ptr) { GtkTreeSelection * selection; - GtkTreeIter iter; + GtkTreeIter app_iter; + GtkTreeIter view_iter; gint type; uint64_t id; + graph_view_handle view; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(g_world_tree_widget)); - if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) + if (!gtk_tree_selection_get_selected(selection, NULL, &app_iter)) { return false; } gtk_tree_model_get( GTK_TREE_MODEL(g_treestore), - &iter, + &app_iter, COL_TYPE, &type, COL_ID, &id, -1); @@ -103,6 +105,25 @@ bool get_selected_app_id(uint64_t * id_ptr) return false; } + if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(g_treestore), &view_iter, &app_iter)) + { + ASSERT_NO_PASS; + return false; + } + + gtk_tree_model_get( + GTK_TREE_MODEL(g_treestore), + &view_iter, + COL_TYPE, &type, + COL_VIEW, &view, + -1); + if (type != entry_type_view) + { + ASSERT_NO_PASS; + return false; + } + + *view_ptr = view; *id_ptr = id; return true; @@ -111,37 +132,69 @@ bool get_selected_app_id(uint64_t * id_ptr) void on_popup_menu_action_app_start(GtkWidget * menuitem, gpointer userdata) { uint64_t id; + ladish_app_supervisor_proxy_handle proxy; + graph_view_handle view; - if (!get_selected_app_id(&id)) + if (!get_selected_app_id(&view, &id)) { return; } log_info("start app %"PRIu64, id); + + proxy = graph_view_get_app_supervisor(view); + ladish_app_supervisor_proxy_start_app(proxy, id); } void on_popup_menu_action_app_stop(GtkWidget * menuitem, gpointer userdata) { uint64_t id; + ladish_app_supervisor_proxy_handle proxy; + graph_view_handle view; - if (!get_selected_app_id(&id)) + if (!get_selected_app_id(&view, &id)) { return; } log_info("stop app %"PRIu64, id); + + proxy = graph_view_get_app_supervisor(view); + ladish_app_supervisor_proxy_stop_app(proxy, id); +} + +void on_popup_menu_action_app_kill(GtkWidget * menuitem, gpointer userdata) +{ + uint64_t id; + ladish_app_supervisor_proxy_handle proxy; + graph_view_handle view; + + if (!get_selected_app_id(&view, &id)) + { + return; + } + + log_info("kill app %"PRIu64, id); + + proxy = graph_view_get_app_supervisor(view); + ladish_app_supervisor_proxy_kill_app(proxy, id); } void on_popup_menu_action_app_remove(GtkWidget * menuitem, gpointer userdata) { uint64_t id; + ladish_app_supervisor_proxy_handle proxy; + graph_view_handle view; - if (!get_selected_app_id(&id)) + if (!get_selected_app_id(&view, &id)) { return; } log_info("remove app %"PRIu64, id); + + proxy = graph_view_get_app_supervisor(view); + ladish_app_supervisor_proxy_remove_app(proxy, id); } void popup_menu(GtkWidget * treeview, GdkEventButton * event) @@ -197,6 +250,13 @@ void popup_menu(GtkWidget * treeview, GdkEventButton * event) g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_remove, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + if (running) + { + menuitem = gtk_menu_item_new_with_label("Kill"); + g_signal_connect(menuitem, "activate", (GCallback)on_popup_menu_action_app_kill, NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } + gtk_widget_show_all(menu); /* Note: event can be NULL here when called from view_onPopupMenu; @@ -429,12 +489,11 @@ free_path: gtk_tree_path_free(path); } -void world_tree_app_state_changed(graph_view_handle view, uint64_t id, const char * name, bool running, bool terminal, uint8_t level) +void world_tree_app_state_changed(graph_view_handle view, uint64_t id, const char * app_name, bool running, bool terminal, uint8_t level) { GtkTreeIter view_iter; GtkTreeIter app_iter; const char * view_name; - const char * app_name; GtkTreePath * path; char * app_name_with_status; @@ -447,7 +506,6 @@ void world_tree_app_state_changed(graph_view_handle view, uint64_t id, const cha path = gtk_tree_model_get_path(GTK_TREE_MODEL(g_treestore), &view_iter); gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &view_iter, COL_NAME, &view_name, -1); - gtk_tree_model_get(GTK_TREE_MODEL(g_treestore), &app_iter, COL_NAME, &app_name, -1); log_info("changing app state '%s':'%s'", view_name, app_name); -- 2.11.4.GIT