diff --git a/daemon/app_supervisor.c b/daemon/app_supervisor.c index 1909cdd3..dc34857d 100644 --- a/daemon/app_supervisor.c +++ b/daemon/app_supervisor.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov * ************************************************************************** * This file contains implementation of app supervisor object @@ -903,17 +903,20 @@ ladish_app_supervisor_set_project_name( return true; } -bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle, pid_t pid) +bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle, pid_t pid, int exit_status) { struct list_head * node_ptr; struct ladish_app * app_ptr; + bool clean; list_for_each(node_ptr, &supervisor_ptr->applist) { app_ptr = list_entry(node_ptr, struct ladish_app, siblings); if (app_ptr->pid == pid) { - log_info("exit of child '%s' detected.", app_ptr->name); + clean = WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0; + + log_info("%s exit of child '%s' detected.", clean ? "clean" : "dirty", app_ptr->name); app_ptr->pid = 0; app_ptr->pgrp = 0; @@ -926,7 +929,7 @@ bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_ha } else { - if (app_ptr->state == LADISH_APP_STATE_STARTED) + if (app_ptr->state == LADISH_APP_STATE_STARTED && !clean) { ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH, "App terminated unexpectedly", app_ptr->name); } diff --git a/daemon/app_supervisor.h b/daemon/app_supervisor.h index 62ffadd4..cc6ed528 100644 --- a/daemon/app_supervisor.h +++ b/daemon/app_supervisor.h @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov * ************************************************************************** * This file contains interface to app supervisor object @@ -165,12 +165,14 @@ ladish_app_supervisor_set_project_name( * This function is called to mark that app has quit. Must not be called from signal handler because app supervisor object is not thread safe. * * @param[in] supervisor_handle supervisor object handle - * @param[in] pid of the app whose termination was detected + * @param[in] pid pid of the app whose termination was detected + * @param[in] exit_statis process exit status as returned by waitpid() */ bool ladish_app_supervisor_child_exit( ladish_app_supervisor_handle supervisor_handle, - pid_t pid); + pid_t pid, + int exit_status); /** * Iterate apps that are owned by supervisor diff --git a/daemon/loader.c b/daemon/loader.c index 37fb94fa..aa0030a9 100644 --- a/daemon/loader.c +++ b/daemon/loader.c @@ -55,6 +55,7 @@ struct loader_child char * project_name; bool dead; + int exit_status; pid_t pid; bool terminal; @@ -72,11 +73,11 @@ struct loader_child char * stderr_buffer_ptr; }; -static void (* g_on_child_exit)(pid_t pid); +static void (* g_on_child_exit)(pid_t pid, int exit_status); static struct list_head g_childs_list; static struct loader_child * -loader_child_find_and_mark_dead(pid_t pid) +loader_child_find(pid_t pid) { struct list_head *node_ptr; struct loader_child *child_ptr; @@ -86,7 +87,6 @@ loader_child_find_and_mark_dead(pid_t pid) child_ptr = list_entry(node_ptr, struct loader_child, siblings); if (child_ptr->pid == pid) { - child_ptr->dead = true; return child_ptr; } } @@ -153,7 +153,7 @@ loader_childs_bury(void) close(child_ptr->stderr); } - g_on_child_exit(child_ptr->pid); + g_on_child_exit(child_ptr->pid, child_ptr->exit_status); free(child_ptr); } } @@ -168,7 +168,7 @@ static void loader_sigchld_handler(int signum) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - child_ptr = loader_child_find_and_mark_dead(pid); + child_ptr = loader_child_find(pid); if (!child_ptr) { @@ -177,11 +177,13 @@ static void loader_sigchld_handler(int signum) else { log_info("Termination of child process '%s' with PID %llu detected", child_ptr->app_name, (unsigned long long)pid); + child_ptr->dead = true; + child_ptr->exit_status = status; } if (WIFEXITED(status)) { - log_info("Child exited, status=%d", WEXITSTATUS(status)); + log_info("Child exited, code=%d", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { @@ -205,7 +207,7 @@ static void loader_sigchld_handler(int signum) } } -void loader_init(void (* on_child_exit)(pid_t pid)) +void loader_init(void (* on_child_exit)(pid_t pid, int exit_status)) { g_on_child_exit = on_child_exit; signal(SIGCHLD, loader_sigchld_handler); diff --git a/daemon/loader.h b/daemon/loader.h index f2ee99f6..537bbdb8 100644 --- a/daemon/loader.h +++ b/daemon/loader.h @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov * ************************************************************************** * This file contains interface to the code that starts programs @@ -27,7 +27,7 @@ #ifndef __LASHD_LOADER_H__ #define __LASHD_LOADER_H__ -void loader_init(void (* on_child_exit)(pid_t pid)); +void loader_init(void (* on_child_exit)(pid_t pid, int exit_status)); bool loader_execute( diff --git a/daemon/studio.c b/daemon/studio.c index 61c8c0db..fcbbd8ec 100644 --- a/daemon/studio.c +++ b/daemon/studio.c @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010, 2011 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov * ************************************************************************** * This file contains part of the studio singleton object implementation @@ -655,6 +655,7 @@ void ladish_studio_uninit(void) struct on_child_exit_context { pid_t pid; + int exit_status; bool found; }; @@ -667,7 +668,7 @@ ladish_studio_on_child_exit_callback( ladish_graph_handle graph, ladish_app_supervisor_handle app_supervisor) { - child_exit_context_ptr->found = ladish_app_supervisor_child_exit(app_supervisor, child_exit_context_ptr->pid); + child_exit_context_ptr->found = ladish_app_supervisor_child_exit(app_supervisor, child_exit_context_ptr->pid, child_exit_context_ptr->exit_status); /* if child is found, return false - it will cause iteration to stop */ /* if child is not found, return true - it will cause next supervisor to be checked */ return !child_exit_context_ptr->found; @@ -675,11 +676,12 @@ ladish_studio_on_child_exit_callback( #undef child_exit_context_ptr -void ladish_studio_on_child_exit(pid_t pid) +void ladish_studio_on_child_exit(pid_t pid, int exit_status) { struct on_child_exit_context context; context.pid = pid; + context.exit_status = exit_status; context.found = false; ladish_studio_iterate_virtual_graphs(&context, ladish_studio_on_child_exit_callback); diff --git a/daemon/studio.h b/daemon/studio.h index 11a01d3c..a40f4154 100644 --- a/daemon/studio.h +++ b/daemon/studio.h @@ -2,7 +2,7 @@ /* * LADI Session Handler (ladish) * - * Copyright (C) 2009, 2010 Nedko Arnaudov + * Copyright (C) 2009, 2010, 2012 Nedko Arnaudov * ************************************************************************** * This file contains interface of the studio singleton object @@ -41,7 +41,7 @@ bool ladish_studio_is_started(void); bool ladish_studios_iterate(void * call_ptr, void * context, bool (* callback)(void * call_ptr, void * context, const char * studio, uint32_t modtime)); bool ladish_studio_delete(void * call_ptr, const char * studio_name); -void ladish_studio_on_child_exit(pid_t pid); +void ladish_studio_on_child_exit(pid_t pid, int exit_status); bool ladish_studio_iterate_virtual_graphs(