1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009, 2010, 2011, 2012 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains implementation of app supervisor object
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h" /* Get _GNU_SOURCE defenition first to have some GNU extension available */
29 #include <sys/types.h>
35 #include "app_supervisor.h"
36 #include "../dbus_constants.h"
38 #include "studio_internal.h"
39 #include "../proxies/notify_proxy.h"
40 #include "../proxies/lash_client_proxy.h"
41 #include "../common/catdup.h"
42 #include "../common/dirhelpers.h"
43 #include "jack_session.h"
47 struct list_head siblings
;
52 char * js_commandline
;
54 char level
[MAX_LEVEL_CHARCOUNT
];
59 int firstborn_refcount
;
60 bool zombie
; /* if true, remove when stopped */
64 struct ladish_app_supervisor
* supervisor
;
67 struct ladish_app_supervisor
75 unsigned int pending_js_saves
;
76 void * save_callback_context
;
77 ladish_save_complete_callback save_callback
;
82 struct list_head applist
;
83 void * on_app_renamed_context
;
84 ladish_app_supervisor_on_app_renamed_callback on_app_renamed
;
87 bool ladish_check_app_level_validity(const char * level
, size_t * len_ptr
)
91 if (len
>= MAX_LEVEL_CHARCOUNT
)
96 if (strcmp(level
, LADISH_APP_LEVEL_0
) != 0 &&
97 strcmp(level
, LADISH_APP_LEVEL_1
) != 0 &&
98 strcmp(level
, LADISH_APP_LEVEL_LASH
) != 0 &&
99 strcmp(level
, LADISH_APP_LEVEL_JACKSESSION
) != 0)
112 static int ladish_level_string_to_integer(const char * level
)
114 if (strcmp(level
, LADISH_APP_LEVEL_0
) == 0)
118 else if (strcmp(level
, LADISH_APP_LEVEL_1
) == 0)
122 else if (strcmp(level
, LADISH_APP_LEVEL_LASH
) == 0 ||
123 strcmp(level
, LADISH_APP_LEVEL_JACKSESSION
) == 0)
133 ladish_app_supervisor_create(
134 ladish_app_supervisor_handle
* supervisor_handle_ptr
,
138 ladish_app_supervisor_on_app_renamed_callback on_app_renamed
)
140 struct ladish_app_supervisor
* supervisor_ptr
;
142 supervisor_ptr
= malloc(sizeof(struct ladish_app_supervisor
));
143 if (supervisor_ptr
== NULL
)
145 log_error("malloc() failed to allocate struct ladish_app_supervisor");
149 supervisor_ptr
->opath
= strdup(opath
);
150 if (supervisor_ptr
->opath
== NULL
)
152 log_error("strdup() failed for app supervisor opath");
153 free(supervisor_ptr
);
157 supervisor_ptr
->name
= strdup(name
);
158 if (supervisor_ptr
->name
== NULL
)
160 log_error("strdup() failed for app supervisor name");
161 free(supervisor_ptr
->opath
);
162 free(supervisor_ptr
);
166 supervisor_ptr
->dir
= NULL
;
168 supervisor_ptr
->js_temp_dir
= NULL
;
169 supervisor_ptr
->js_dir
= NULL
;
170 supervisor_ptr
->pending_js_saves
= 0;
171 supervisor_ptr
->save_callback_context
= NULL
;
172 supervisor_ptr
->save_callback
= NULL
;
174 supervisor_ptr
->project_name
= NULL
;
176 supervisor_ptr
->version
= 0;
177 supervisor_ptr
->next_id
= 1;
179 INIT_LIST_HEAD(&supervisor_ptr
->applist
);
181 supervisor_ptr
->on_app_renamed_context
= context
;
182 supervisor_ptr
->on_app_renamed
= on_app_renamed
;
184 *supervisor_handle_ptr
= (ladish_app_supervisor_handle
)supervisor_ptr
;
189 struct ladish_app
* ladish_app_supervisor_find_app_by_id_internal(struct ladish_app_supervisor
* supervisor_ptr
, uint64_t id
)
191 struct list_head
* node_ptr
;
192 struct ladish_app
* app_ptr
;
194 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
196 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
197 if (app_ptr
->id
== id
)
206 void remove_app_internal(struct ladish_app_supervisor
* supervisor_ptr
, struct ladish_app
* app_ptr
)
208 ASSERT(app_ptr
->pid
== 0); /* Removing not-stoped app? Zombies will make a rebellion! */
210 list_del(&app_ptr
->siblings
);
212 supervisor_ptr
->version
++;
215 cdbus_g_dbus_connection
,
216 supervisor_ptr
->opath
,
217 IFACE_APP_SUPERVISOR
,
220 &supervisor_ptr
->version
,
223 free(app_ptr
->dbus_name
);
225 free(app_ptr
->commandline
);
226 free(app_ptr
->js_commandline
);
230 void emit_app_state_changed(struct ladish_app_supervisor
* supervisor_ptr
, struct ladish_app
* app_ptr
)
233 dbus_bool_t terminal
;
234 const char * level_str
;
237 running
= app_ptr
->pid
!= 0;
238 terminal
= app_ptr
->terminal
;
239 level_str
= app_ptr
->level
;
240 level_byte
= ladish_level_string_to_integer(app_ptr
->level
);
242 supervisor_ptr
->version
++;
245 cdbus_g_dbus_connection
,
246 supervisor_ptr
->opath
,
247 IFACE_APP_SUPERVISOR
,
250 &supervisor_ptr
->version
,
258 cdbus_g_dbus_connection
,
259 supervisor_ptr
->opath
,
260 IFACE_APP_SUPERVISOR
,
263 &supervisor_ptr
->version
,
271 static void ladish_js_save_complete(struct ladish_app_supervisor
* supervisor_ptr
)
273 struct list_head
* node_ptr
;
274 struct ladish_app
* app_ptr
;
277 ASSERT(supervisor_ptr
->js_temp_dir
!= NULL
);
278 ASSERT(supervisor_ptr
->js_dir
!= NULL
);
279 ASSERT(supervisor_ptr
->pending_js_saves
== 0);
281 /* find whether all strdup() calls for new commandlines succeeded */
282 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
284 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
285 if (app_ptr
->state
== LADISH_APP_STATE_STARTED
&&
286 strcmp(app_ptr
->level
, LADISH_APP_LEVEL_JACKSESSION
) == 0 &&
287 app_ptr
->js_commandline
== NULL
)
288 { /* a strdup() call has failed, or js save failed for some other reason,
289 free js commandline buffers allocated by succeeded strdup() calls */
290 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
292 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
293 free(app_ptr
->js_commandline
);
294 app_ptr
->js_commandline
= NULL
;
297 goto fail_rm_temp_dir
;
301 /* move js_dir to js_dir.1; move js_temp_dir to js_dir */
302 success
= ladish_rotate(supervisor_ptr
->js_temp_dir
, supervisor_ptr
->js_dir
, 10);
305 goto fail_rm_temp_dir
;
308 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
310 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
311 if (app_ptr
->state
== LADISH_APP_STATE_STARTED
&&
312 strcmp(app_ptr
->level
, LADISH_APP_LEVEL_JACKSESSION
) == 0)
314 ASSERT(app_ptr
->commandline
!= NULL
);
315 ASSERT(app_ptr
->js_commandline
!= NULL
);
316 free(app_ptr
->commandline
);
317 app_ptr
->commandline
= app_ptr
->js_commandline
;
318 app_ptr
->js_commandline
= NULL
;
325 if (!ladish_rmdir_recursive(supervisor_ptr
->js_temp_dir
))
327 log_error("Cannot remove JS temp dir '%s'", supervisor_ptr
->js_temp_dir
);
331 free(supervisor_ptr
->js_temp_dir
);
332 supervisor_ptr
->js_temp_dir
= NULL
;
334 supervisor_ptr
->save_callback(supervisor_ptr
->save_callback_context
, success
);
335 supervisor_ptr
->save_callback
= NULL
;
336 supervisor_ptr
->save_callback_context
= NULL
;
339 #define supervisor_ptr ((struct ladish_app_supervisor *)supervisor_handle)
341 const char * ladish_app_supervisor_get_opath(ladish_app_supervisor_handle supervisor_handle
)
343 return supervisor_ptr
->opath
;
346 ladish_app_handle
ladish_app_supervisor_find_app_by_name(ladish_app_supervisor_handle supervisor_handle
, const char * name
)
348 struct list_head
* node_ptr
;
349 struct ladish_app
* app_ptr
;
351 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
353 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
354 if (strcmp(app_ptr
->name
, name
) == 0)
356 return (ladish_app_handle
)app_ptr
;
363 ladish_app_handle
ladish_app_supervisor_find_app_by_id(ladish_app_supervisor_handle supervisor_handle
, uint64_t id
)
365 return (ladish_app_handle
)ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
368 ladish_app_handle
ladish_app_supervisor_find_app_by_pid(ladish_app_supervisor_handle supervisor_handle
, pid_t pid
)
370 struct list_head
* node_ptr
;
371 struct ladish_app
* app_ptr
;
373 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
375 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
376 if (app_ptr
->pid
== pid
)
378 //log_info("app \"%s\" found by pid %llu", app_ptr->name, (unsigned long long)pid);
379 return (ladish_app_handle
)app_ptr
;
386 ladish_app_handle
ladish_app_supervisor_find_app_by_uuid(ladish_app_supervisor_handle supervisor_handle
, const uuid_t uuid
)
388 struct list_head
* node_ptr
;
389 struct ladish_app
* app_ptr
;
391 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
393 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
394 if (uuid_compare(app_ptr
->uuid
, uuid
) == 0)
396 return (ladish_app_handle
)app_ptr
;
404 ladish_app_supervisor_add(
405 ladish_app_supervisor_handle supervisor_handle
,
409 const char * command
,
413 struct ladish_app
* app_ptr
;
415 dbus_bool_t dbus_terminal
;
419 if (!ladish_check_app_level_validity(level
, &len
))
421 log_error("invalid level '%s'", level
);
425 if (strcmp(level
, LADISH_APP_LEVEL_JACKSESSION
) == 0 &&
426 supervisor_ptr
->dir
== NULL
)
428 log_error("jack session apps need directory");
432 app_ptr
= malloc(sizeof(struct ladish_app
));
435 log_error("malloc of struct ladish_app failed");
439 app_ptr
->name
= strdup(name
);
440 if (app_ptr
->name
== NULL
)
442 log_error("strdup() failed for app name");
446 app_ptr
->commandline
= strdup(command
);
447 if (app_ptr
->commandline
== NULL
)
449 log_error("strdup() failed for app commandline");
453 app_ptr
->js_commandline
= NULL
;
455 app_ptr
->dbus_name
= NULL
;
457 app_ptr
->terminal
= terminal
;
458 memcpy(app_ptr
->level
, level
, len
+ 1);
461 app_ptr
->firstborn_pid
= 0;
462 app_ptr
->firstborn_pgrp
= 0;
463 app_ptr
->firstborn_refcount
= 0;
465 app_ptr
->id
= supervisor_ptr
->next_id
++;
466 if (uuid
== NULL
|| uuid_is_null(uuid
))
468 uuid_generate(app_ptr
->uuid
);
472 uuid_copy(app_ptr
->uuid
, uuid
);
475 app_ptr
->zombie
= false;
476 app_ptr
->state
= LADISH_APP_STATE_STOPPED
;
477 app_ptr
->autorun
= autorun
;
478 app_ptr
->supervisor
= supervisor_ptr
;
479 list_add_tail(&app_ptr
->siblings
, &supervisor_ptr
->applist
);
481 supervisor_ptr
->version
++;
484 dbus_terminal
= terminal
;
485 level
= app_ptr
->level
;
486 level_byte
= ladish_level_string_to_integer(app_ptr
->level
);
488 cdbus_g_dbus_connection
,
489 supervisor_ptr
->opath
,
490 IFACE_APP_SUPERVISOR
,
493 &supervisor_ptr
->version
,
500 cdbus_g_dbus_connection
,
501 supervisor_ptr
->opath
,
502 IFACE_APP_SUPERVISOR
,
505 &supervisor_ptr
->version
,
512 return (ladish_app_handle
)app_ptr
;
522 static void ladish_app_send_signal(struct ladish_app
* app_ptr
, int sig
, bool prefer_firstborn
)
525 const char * signal_name
;
527 ASSERT(app_ptr
->state
= LADISH_APP_STATE_STARTED
);
532 signal_name
= "SIGTERM";
535 signal_name
= "SIGKILL";
538 signal_name
= "SIGUSR1";
541 signal_name
= strsignal(sig
);
542 if (signal_name
== NULL
)
544 signal_name
= "unknown";
548 if (app_ptr
->pid
== 0)
550 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
);
559 if (app_ptr
->pgrp
== 0)
561 app_ptr
->pgrp
= getpgid(app_ptr
->pid
);
562 if (app_ptr
->pgrp
== -1)
567 log_error("getpgid(%u) failed. %s (%d)", (unsigned int)app_ptr
->pid
, strerror(errno
), errno
);
572 if (app_ptr
->firstborn_pid
!= 0)
574 app_ptr
->firstborn_pgrp
= getpgid(app_ptr
->firstborn_pid
);
575 if (app_ptr
->firstborn_pgrp
== -1)
577 app_ptr
->firstborn_pgrp
= 0;
580 log_error("getpgid(%u) failed (firstborn). %s (%d)", (unsigned int)app_ptr
->firstborn_pid
, strerror(errno
), errno
);
585 if (app_ptr
->pgrp
!= 0)
587 log_info("sending signal %d (%s) to pgrp %u ('%s')", sig
, signal_name
, (unsigned int)app_ptr
->pgrp
, app_ptr
->name
);
589 if (app_ptr
->pgrp
<= 1)
595 killpg(app_ptr
->pgrp
, sig
);
597 if (app_ptr
->firstborn_pid
!= 0)
599 if (app_ptr
->firstborn_pgrp
!= 0)
601 if (app_ptr
->firstborn_pgrp
<= 1)
607 if (app_ptr
->firstborn_pgrp
!= app_ptr
->pgrp
)
609 log_info("sending signal %d (%s) to firstborn pgrp %u ('%s')", sig
, signal_name
, (unsigned int)app_ptr
->firstborn_pgrp
, app_ptr
->name
);
611 killpg(app_ptr
->firstborn_pgrp
, sig
);
615 /* fall through to sending signal to pid */
622 /* fall through to sending signal to pid */
624 if (app_ptr
->pid
<= 1)
630 if (prefer_firstborn
&& app_ptr
->firstborn_pid
!= 0)
632 pid
= app_ptr
->firstborn_pid
;
645 log_info("sending signal %d (%s) to '%s' with pid %u", sig
, signal_name
, app_ptr
->name
, (unsigned int)pid
);
650 static inline void ladish_app_initiate_lash_save(struct ladish_app
* app_ptr
, const char * base_dir
)
655 if (base_dir
== NULL
)
657 log_error("Cannot initiate LASH save because base dir is unknown");
662 uuid_unparse(app_ptr
->uuid
, uuid_str
);
663 app_dir
= catdup3(base_dir
, "/lash_apps/", uuid_str
);
666 log_error("Cannot initiate LASH save because of memory allocation failure.");
670 if (!ensure_dir_exist(app_dir
, S_IRWXU
| S_IRWXG
| S_IRWXO
))
675 if (lash_client_proxy_save(app_ptr
->dbus_name
, app_dir
))
677 log_info("LASH Save into '%s' initiated for '%s' with D-Bus name '%s'", app_dir
, app_ptr
->name
, app_ptr
->dbus_name
);
686 static inline void ladish_app_initiate_lash_restore(struct ladish_app
* app_ptr
, const char * base_dir
)
692 if (base_dir
== NULL
)
694 log_error("Cannot initiate LASH restore because base dir is unknown");
699 uuid_unparse(app_ptr
->uuid
, uuid_str
);
700 app_dir
= catdup3(base_dir
, "/lash_apps/", uuid_str
);
703 log_error("Cannot initiate LASH restore because of memory allocation failure.");
707 if (!check_dir_exists(app_dir
))
709 log_info("Not initiating LASH restore because of app directory '%s' does not exist.", app_dir
);
713 if (lash_client_proxy_restore(app_ptr
->dbus_name
, app_dir
))
715 log_info("LASH Save from '%s' initiated for '%s' with D-Bus name '%s'", app_dir
, app_ptr
->name
, app_ptr
->dbus_name
);
724 #define app_ptr ((struct ladish_app *)context)
726 static void ladish_js_app_save_complete(void * context
, const char * commandline
)
728 if (commandline
!= NULL
)
730 log_info("JS app saved, commandline '%s'", commandline
);
731 ASSERT(app_ptr
->supervisor
->js_temp_dir
!= NULL
);
733 ASSERT(app_ptr
->js_commandline
== NULL
);
734 app_ptr
->js_commandline
= strdup(commandline
);
735 if (app_ptr
->js_commandline
== NULL
)
737 log_error("strdup() failed for JS app '%s' commandline '%s'", app_ptr
->name
, commandline
);
742 ASSERT(app_ptr
->js_commandline
== NULL
);
743 log_error("JACK session save failed for JS app '%s'", app_ptr
->name
);
746 if (app_ptr
->supervisor
->pending_js_saves
!= 1)
748 ASSERT(app_ptr
->supervisor
->pending_js_saves
> 1);
749 app_ptr
->supervisor
->pending_js_saves
--;
750 log_info("%u more JS apps are still saving", app_ptr
->supervisor
->pending_js_saves
);
754 log_info("No more pending JS app saves");
755 app_ptr
->supervisor
->pending_js_saves
= 0;
757 ladish_js_save_complete(app_ptr
->supervisor
);
762 static inline void ladish_app_initiate_save(struct ladish_app
* app_ptr
)
764 if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_LASH
) == 0 &&
765 app_ptr
->dbus_name
!= NULL
)
767 ladish_app_initiate_lash_save(app_ptr
, app_ptr
->supervisor
->dir
!= NULL
? app_ptr
->supervisor
->dir
: g_base_dir
);
769 else if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_JACKSESSION
) == 0)
771 log_info("Initiating JACK session save for '%s'", app_ptr
->name
);
772 if (!ladish_js_save_app(app_ptr
->uuid
, app_ptr
->supervisor
->js_temp_dir
, app_ptr
, ladish_js_app_save_complete
))
774 ladish_js_app_save_complete(app_ptr
, NULL
);
777 else if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_1
) == 0)
779 ladish_app_send_signal(app_ptr
, SIGUSR1
, true);
783 static inline void ladish_app_initiate_stop(struct ladish_app
* app_ptr
)
785 if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_LASH
) == 0 &&
786 app_ptr
->dbus_name
!= NULL
&&
787 lash_client_proxy_quit(app_ptr
->dbus_name
))
789 log_info("LASH Quit initiated for '%s' with D-Bus name '%s'", app_ptr
->name
, app_ptr
->dbus_name
);
793 ladish_app_send_signal(app_ptr
, SIGTERM
, false);
796 app_ptr
->state
= LADISH_APP_STATE_STOPPING
;
799 bool ladish_app_supervisor_clear(ladish_app_supervisor_handle supervisor_handle
)
801 struct list_head
* node_ptr
;
802 struct list_head
* safe_node_ptr
;
803 struct ladish_app
* app_ptr
;
806 free(supervisor_ptr
->js_temp_dir
);
807 supervisor_ptr
->js_temp_dir
= NULL
;
808 free(supervisor_ptr
->js_dir
);
809 supervisor_ptr
->js_dir
= NULL
;
810 free(supervisor_ptr
->dir
);
811 supervisor_ptr
->dir
= NULL
;
813 free(supervisor_ptr
->project_name
);
814 supervisor_ptr
->project_name
= NULL
;
818 list_for_each_safe(node_ptr
, safe_node_ptr
, &supervisor_ptr
->applist
)
820 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
821 if (app_ptr
->pid
!= 0)
823 log_info("terminating '%s'...", app_ptr
->name
);
824 ladish_app_initiate_stop(app_ptr
);
825 app_ptr
->zombie
= true;
830 log_info("removing '%s'", app_ptr
->name
);
831 remove_app_internal(supervisor_ptr
, app_ptr
);
838 void ladish_app_supervisor_destroy(ladish_app_supervisor_handle supervisor_handle
)
840 ladish_app_supervisor_clear(supervisor_handle
);
841 free(supervisor_ptr
->name
);
842 free(supervisor_ptr
->opath
);
843 free(supervisor_ptr
);
847 ladish_app_supervisor_set_directory(
848 ladish_app_supervisor_handle supervisor_handle
,
854 ASSERT(supervisor_ptr
->pending_js_saves
== 0);
859 log_error("strdup(\"%s\") failed", dir
);
863 js_dir
= catdup(dir
, "/js_apps");
866 log_error("catdup() failed to compose supervisor js dir path");
871 free(supervisor_ptr
->dir
);
872 supervisor_ptr
->dir
= dup
;
874 free(supervisor_ptr
->js_dir
);
875 supervisor_ptr
->js_dir
= js_dir
;
881 ladish_app_supervisor_set_project_name(
882 ladish_app_supervisor_handle supervisor_handle
,
883 const char * project_name
)
887 if (project_name
!= NULL
)
889 dup
= strdup(project_name
);
892 log_error("strdup(\"%s\") failed", project_name
);
901 free(supervisor_ptr
->project_name
);
902 supervisor_ptr
->project_name
= dup
;
907 bool ladish_app_supervisor_child_exit(ladish_app_supervisor_handle supervisor_handle
, pid_t pid
, int exit_status
)
909 struct list_head
* node_ptr
;
910 struct ladish_app
* app_ptr
;
913 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
915 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
916 if (app_ptr
->pid
== pid
)
918 clean
= WIFEXITED(exit_status
) && WEXITSTATUS(exit_status
) == 0;
920 log_info("%s exit of child '%s' detected.", clean
? "clean" : "dirty", app_ptr
->name
);
924 /* firstborn pid and pgrp is not reset here because it is refcounted
925 and managed independently through the add/del_pid() methods */
929 remove_app_internal(supervisor_ptr
, app_ptr
);
933 if (app_ptr
->state
== LADISH_APP_STATE_STARTED
&& !clean
)
935 ladish_notify_simple(LADISH_NOTIFY_URGENCY_HIGH
, "App terminated unexpectedly", app_ptr
->name
);
938 app_ptr
->state
= LADISH_APP_STATE_STOPPED
;
940 emit_app_state_changed(supervisor_ptr
, app_ptr
);
951 ladish_app_supervisor_enum(
952 ladish_app_supervisor_handle supervisor_handle
,
954 ladish_app_supervisor_enum_callback callback
)
956 struct list_head
* node_ptr
;
957 struct ladish_app
* app_ptr
;
959 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
961 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
963 if (!callback(context
, app_ptr
->name
, app_ptr
->pid
!= 0, app_ptr
->commandline
, app_ptr
->terminal
, app_ptr
->level
, app_ptr
->pid
, app_ptr
->uuid
))
972 #define app_ptr ((struct ladish_app *)app_handle)
974 bool ladish_app_supervisor_start_app(ladish_app_supervisor_handle supervisor_handle
, ladish_app_handle app_handle
)
981 app_ptr
->zombie
= false;
983 ASSERT(app_ptr
->pid
== 0);
985 set_env_vars
= ladish_level_string_to_integer(app_ptr
->level
) >= 2;
987 if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_JACKSESSION
) == 0)
989 uuid_unparse(app_ptr
->uuid
, uuid_str
);
990 js_dir
= catdup4(supervisor_ptr
->js_dir
, "/", uuid_str
, "/");
993 log_error("catdup4() failed to compose app jack session dir");
1002 ret
= loader_execute(
1003 supervisor_ptr
->name
,
1004 supervisor_ptr
->project_name
,
1006 supervisor_ptr
->dir
!= NULL
? supervisor_ptr
->dir
: "/",
1009 app_ptr
->commandline
,
1020 ASSERT(app_ptr
->pid
!= 0);
1021 app_ptr
->state
= LADISH_APP_STATE_STARTED
;
1023 emit_app_state_changed(supervisor_ptr
, app_ptr
);
1027 void ladish_app_supervisor_remove_app(ladish_app_supervisor_handle supervisor_handle
, ladish_app_handle app_handle
)
1029 remove_app_internal(supervisor_ptr
, app_ptr
);
1032 unsigned int ladish_app_get_state(ladish_app_handle app_handle
)
1034 return app_ptr
->state
;
1037 bool ladish_app_is_running(ladish_app_handle app_handle
)
1039 return app_ptr
->pid
!= 0;
1042 const char * ladish_app_get_name(ladish_app_handle app_handle
)
1044 return app_ptr
->name
;
1047 void ladish_app_get_uuid(ladish_app_handle app_handle
, uuid_t uuid
)
1049 uuid_copy(uuid
, app_ptr
->uuid
);
1052 void ladish_app_stop(ladish_app_handle app_handle
)
1054 ladish_app_initiate_stop(app_ptr
);
1057 void ladish_app_kill(ladish_app_handle app_handle
)
1059 ladish_app_send_signal(app_ptr
, SIGKILL
, false);
1060 app_ptr
->state
= LADISH_APP_STATE_KILL
;
1063 void ladish_app_restore(ladish_app_handle app_handle
)
1065 if (strcmp(app_ptr
->level
, LADISH_APP_LEVEL_LASH
) == 0 &&
1066 app_ptr
->dbus_name
!= NULL
)
1068 ladish_app_initiate_lash_restore(app_ptr
, app_ptr
->supervisor
->dir
!= NULL
? app_ptr
->supervisor
->dir
: g_base_dir
);
1072 void ladish_app_add_pid(ladish_app_handle app_handle
, pid_t pid
)
1074 if (app_ptr
->pid
== 0)
1076 log_error("Associating pid with stopped app does not make sense");
1081 if (pid
<= 1) /* catch -1, 0 and 1 */
1083 log_error("Refusing domination by ignoring pid %d", (int)pid
);
1088 if (app_ptr
->pid
== pid
)
1089 { /* The top level process that is already known */
1093 if (app_ptr
->firstborn_pid
!= 0)
1094 { /* Ignore non-first children */
1095 if (app_ptr
->firstborn_pid
== pid
)
1097 app_ptr
->firstborn_refcount
++;
1102 log_info("First grandchild with pid %u", (unsigned int)pid
);
1103 app_ptr
->firstborn_pid
= pid
;
1104 ASSERT(app_ptr
->firstborn_refcount
== 0);
1105 app_ptr
->firstborn_refcount
= 1;
1108 void ladish_app_del_pid(ladish_app_handle app_handle
, pid_t pid
)
1110 if (app_ptr
->firstborn_pid
!= 0 && app_ptr
->firstborn_pid
== pid
)
1112 ASSERT(app_ptr
->firstborn_refcount
> 0);
1113 app_ptr
->firstborn_refcount
--;
1114 if (app_ptr
->firstborn_refcount
> 0)
1118 log_info("First grandchild with pid %u has gone", (unsigned int)pid
);
1119 app_ptr
->firstborn_pid
= 0;
1120 app_ptr
->firstborn_pgrp
= 0;
1121 app_ptr
->firstborn_refcount
= 0;
1125 bool ladish_app_set_dbus_name(ladish_app_handle app_handle
, const char * name
)
1132 log_error("strdup() failed for app dbus name");
1136 free(app_ptr
->dbus_name
);
1137 app_ptr
->dbus_name
= dup
;
1143 void ladish_app_supervisor_autorun(ladish_app_supervisor_handle supervisor_handle
)
1145 struct list_head
* node_ptr
;
1146 struct ladish_app
* app_ptr
;
1148 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1150 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1152 if (!app_ptr
->autorun
)
1157 app_ptr
->autorun
= false;
1159 log_info("autorun('%s', %s, '%s') called", app_ptr
->name
, app_ptr
->terminal
? "terminal" : "shell", app_ptr
->commandline
);
1161 if (!ladish_app_supervisor_start_app((ladish_app_supervisor_handle
)supervisor_ptr
, (ladish_app_handle
)app_ptr
))
1163 log_error("Execution of '%s' failed", app_ptr
->commandline
);
1169 void ladish_app_supervisor_stop(ladish_app_supervisor_handle supervisor_handle
)
1171 struct list_head
* node_ptr
;
1172 struct ladish_app
* app_ptr
;
1174 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1176 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1177 if (app_ptr
->pid
!= 0)
1179 log_info("terminating '%s'...", app_ptr
->name
);
1180 app_ptr
->autorun
= true;
1181 ladish_app_initiate_stop(app_ptr
);
1187 ladish_app_supervisor_save(
1188 ladish_app_supervisor_handle supervisor_handle
,
1190 ladish_save_complete_callback callback
)
1192 struct list_head
* node_ptr
;
1193 struct ladish_app
* app_ptr
;
1196 ASSERT(callback
!= NULL
);
1198 ASSERT(supervisor_ptr
->js_temp_dir
== NULL
);
1199 ASSERT(supervisor_ptr
->pending_js_saves
== 0);
1200 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1202 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1203 if (app_ptr
->state
== LADISH_APP_STATE_STARTED
&&
1204 strcmp(app_ptr
->level
, LADISH_APP_LEVEL_JACKSESSION
) == 0)
1206 ASSERT(app_ptr
->js_commandline
== NULL
);
1207 supervisor_ptr
->pending_js_saves
++;
1211 supervisor_ptr
->save_callback_context
= context
;
1212 supervisor_ptr
->save_callback
= callback
;
1214 if (supervisor_ptr
->pending_js_saves
> 0)
1216 ASSERT(supervisor_ptr
->dir
!= NULL
);
1217 supervisor_ptr
->js_temp_dir
= catdup(supervisor_ptr
->dir
, "/js_apps.tmpXXXXXX");
1218 if (supervisor_ptr
->js_temp_dir
== NULL
)
1220 log_error("catdup() failed to compose supervisor js temp dir path template");
1221 goto reset_js_pending_saves
;
1224 if (mkdtemp(supervisor_ptr
->js_temp_dir
) == NULL
)
1226 log_error("mkdtemp('%s') failed. errno = %d (%s)", supervisor_ptr
->js_temp_dir
, errno
, strerror(errno
));
1227 goto free_js_temp_dir
;
1230 log_info("saving %u JACK session apps to '%s'", supervisor_ptr
->pending_js_saves
, supervisor_ptr
->js_temp_dir
);
1233 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1235 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1236 if (app_ptr
->state
!= LADISH_APP_STATE_STARTED
)
1241 if (app_ptr
->pid
== 0)
1247 ladish_app_initiate_save(app_ptr
);
1254 free(supervisor_ptr
->js_temp_dir
);
1255 supervisor_ptr
->js_temp_dir
= NULL
;
1256 reset_js_pending_saves
:
1257 supervisor_ptr
->pending_js_saves
= 0;
1260 if (supervisor_ptr
->pending_js_saves
== 0 && supervisor_ptr
->save_callback
!= NULL
)
1261 { /* Room/studio without js apps.
1262 In case of ladish_js_save_app() failure,
1263 the callback will either be called already or
1264 will be called later when all pending js app saves are done.
1265 In former case callback will be NULL.
1266 In latter case pending_js_saves will be greater than zero. */
1267 ASSERT(supervisor_ptr
->save_callback
== callback
);
1268 ASSERT(supervisor_ptr
->save_callback_context
= context
);
1269 callback(context
, success
);
1270 supervisor_ptr
->save_callback
= NULL
;
1271 supervisor_ptr
->save_callback_context
= NULL
;
1275 const char * ladish_app_supervisor_get_name(ladish_app_supervisor_handle supervisor_handle
)
1277 return supervisor_ptr
->name
;
1280 unsigned int ladish_app_supervisor_get_running_app_count(ladish_app_supervisor_handle supervisor_handle
)
1282 struct list_head
* node_ptr
;
1283 struct ladish_app
* app_ptr
;
1284 unsigned int counter
;
1287 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1289 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1290 if (app_ptr
->pid
!= 0)
1299 bool ladish_app_supervisor_has_apps(ladish_app_supervisor_handle supervisor_handle
)
1301 return !list_empty(&supervisor_ptr
->applist
);
1304 void ladish_app_supervisor_dump(ladish_app_supervisor_handle supervisor_handle
)
1306 struct list_head
* node_ptr
;
1307 struct ladish_app
* app_ptr
;
1310 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1312 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1313 uuid_unparse(app_ptr
->uuid
, uuid_str
);
1314 log_info("app '%s' with commandline '%s'", app_ptr
->name
, app_ptr
->commandline
);
1315 log_info(" %s", uuid_str
);
1316 log_info(" %s, %s, level '%s'", app_ptr
->terminal
? "terminal" : "shell", app_ptr
->autorun
? "autorun" : "stopped", app_ptr
->level
);
1320 #undef supervisor_ptr
1322 /**********************************************************************************/
1324 /**********************************************************************************/
1326 #define supervisor_ptr ((struct ladish_app_supervisor *)call_ptr->iface_context)
1328 static void get_version(struct cdbus_method_call
* call_ptr
)
1334 cdbus_method_return_new_single(call_ptr
, DBUS_TYPE_UINT32
, &version
);
1337 static void get_all_multiversion(struct cdbus_method_call
* call_ptr
, int version
)
1339 DBusMessageIter iter
, array_iter
, struct_iter
;
1340 struct list_head
* node_ptr
;
1341 struct ladish_app
* app_ptr
;
1342 dbus_bool_t running
;
1343 dbus_bool_t terminal
;
1344 const char * level_str
;
1347 //log_info("get_all called");
1349 call_ptr
->reply
= dbus_message_new_method_return(call_ptr
->message
);
1350 if (call_ptr
->reply
== NULL
)
1355 dbus_message_iter_init_append(call_ptr
->reply
, &iter
);
1357 if (!dbus_message_iter_append_basic(&iter
, DBUS_TYPE_UINT64
, &supervisor_ptr
->version
))
1362 if (!dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
, version
== 1 ? "(tsbby)" : "(tsbbs)", &array_iter
))
1367 list_for_each(node_ptr
, &supervisor_ptr
->applist
)
1369 app_ptr
= list_entry(node_ptr
, struct ladish_app
, siblings
);
1371 log_info("app '%s' (%llu)", app_ptr
->name
, (unsigned long long)app_ptr
->id
);
1373 if (!dbus_message_iter_open_container (&array_iter
, DBUS_TYPE_STRUCT
, NULL
, &struct_iter
))
1378 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_UINT64
, &app_ptr
->id
))
1383 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_STRING
, &app_ptr
->name
))
1388 running
= app_ptr
->pid
!= 0;
1389 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BOOLEAN
, &running
))
1394 terminal
= app_ptr
->terminal
;
1395 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BOOLEAN
, &terminal
))
1402 level_byte
= ladish_level_string_to_integer(app_ptr
->level
);
1403 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_BYTE
, &level_byte
))
1410 ASSERT(version
== 2);
1412 level_str
= app_ptr
->level
;
1413 if (!dbus_message_iter_append_basic(&struct_iter
, DBUS_TYPE_STRING
, &level_str
))
1419 if (!dbus_message_iter_close_container(&array_iter
, &struct_iter
))
1425 if (!dbus_message_iter_close_container(&iter
, &array_iter
))
1433 dbus_message_unref(call_ptr
->reply
);
1434 call_ptr
->reply
= NULL
;
1437 log_error("Ran out of memory trying to construct method return");
1440 static void get_all1(struct cdbus_method_call
* call_ptr
)
1442 get_all_multiversion(call_ptr
, 1);
1445 static void get_all2(struct cdbus_method_call
* call_ptr
)
1447 get_all_multiversion(call_ptr
, 2);
1450 static void run_custom1(struct cdbus_method_call
* call_ptr
)
1452 dbus_bool_t terminal
;
1453 const char * commandline
;
1457 if (!dbus_message_get_args(
1459 &cdbus_g_dbus_error
,
1460 DBUS_TYPE_BOOLEAN
, &terminal
,
1461 DBUS_TYPE_STRING
, &commandline
,
1462 DBUS_TYPE_STRING
, &name
,
1463 DBUS_TYPE_BYTE
, &level
,
1466 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1467 dbus_error_free(&cdbus_g_dbus_error
);
1471 log_info("%s('%s', %s, '%s', %"PRIu8
") called", call_ptr
->method_name
, name
, terminal
? "terminal" : "shell", commandline
, level
);
1475 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "invalid integer level %"PRIu8
, level
);
1479 if (ladish_command_new_app(
1481 ladish_studio_get_cmd_queue(),
1482 supervisor_ptr
->opath
,
1486 level
== 0 ? LADISH_APP_LEVEL_0
: LADISH_APP_LEVEL_1
))
1488 cdbus_method_return_new_void(call_ptr
);
1492 static void run_custom2(struct cdbus_method_call
* call_ptr
)
1494 dbus_bool_t terminal
;
1495 const char * commandline
;
1499 if (!dbus_message_get_args(
1501 &cdbus_g_dbus_error
,
1502 DBUS_TYPE_BOOLEAN
, &terminal
,
1503 DBUS_TYPE_STRING
, &commandline
,
1504 DBUS_TYPE_STRING
, &name
,
1505 DBUS_TYPE_STRING
, &level
,
1508 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1509 dbus_error_free(&cdbus_g_dbus_error
);
1513 log_info("%s('%s', %s, '%s', '%s') called", call_ptr
->method_name
, name
, terminal
? "terminal" : "shell", commandline
, level
);
1515 if (!ladish_check_app_level_validity(level
, NULL
))
1517 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "invalid level '%s'", level
);
1521 if (ladish_command_new_app(
1523 ladish_studio_get_cmd_queue(),
1524 supervisor_ptr
->opath
,
1530 cdbus_method_return_new_void(call_ptr
);
1534 static void start_app(struct cdbus_method_call
* call_ptr
)
1538 if (!dbus_message_get_args(
1540 &cdbus_g_dbus_error
,
1541 DBUS_TYPE_UINT64
, &id
,
1544 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1545 dbus_error_free(&cdbus_g_dbus_error
);
1549 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_STARTED
))
1551 cdbus_method_return_new_void(call_ptr
);
1555 static void stop_app(struct cdbus_method_call
* call_ptr
)
1559 if (!dbus_message_get_args(
1561 &cdbus_g_dbus_error
,
1562 DBUS_TYPE_UINT64
, &id
,
1565 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1566 dbus_error_free(&cdbus_g_dbus_error
);
1570 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_STOPPED
))
1572 cdbus_method_return_new_void(call_ptr
);
1576 static void kill_app(struct cdbus_method_call
* call_ptr
)
1580 if (!dbus_message_get_args(
1582 &cdbus_g_dbus_error
,
1583 DBUS_TYPE_UINT64
, &id
,
1586 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1587 dbus_error_free(&cdbus_g_dbus_error
);
1591 if (ladish_command_change_app_state(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
, LADISH_APP_STATE_KILL
))
1593 cdbus_method_return_new_void(call_ptr
);
1597 static void get_app_properties_multiversion(struct cdbus_method_call
* call_ptr
, int version
)
1600 struct ladish_app
* app_ptr
;
1601 dbus_bool_t running
;
1602 dbus_bool_t terminal
;
1603 const char * level_str
;
1608 if (!dbus_message_get_args(
1610 &cdbus_g_dbus_error
,
1611 DBUS_TYPE_UINT64
, &id
,
1614 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1615 dbus_error_free(&cdbus_g_dbus_error
);
1619 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
1620 if (app_ptr
== NULL
)
1622 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
1626 running
= app_ptr
->pid
!= 0;
1627 terminal
= app_ptr
->terminal
;
1630 level_byte
= ladish_level_string_to_integer(app_ptr
->level
);
1631 level_type
= DBUS_TYPE_BYTE
;
1632 level_ptr
= &level_byte
;
1636 ASSERT(version
== 2);
1637 level_str
= app_ptr
->level
;
1638 level_type
= DBUS_TYPE_STRING
;
1639 level_ptr
= &level_str
;
1642 call_ptr
->reply
= dbus_message_new_method_return(call_ptr
->message
);
1643 if (call_ptr
->reply
== NULL
)
1648 if (!dbus_message_append_args(
1650 DBUS_TYPE_STRING
, &app_ptr
->name
,
1651 DBUS_TYPE_STRING
, &app_ptr
->commandline
,
1652 DBUS_TYPE_BOOLEAN
, &running
,
1653 DBUS_TYPE_BOOLEAN
, &terminal
,
1654 level_type
, level_ptr
,
1663 dbus_message_unref(call_ptr
->reply
);
1664 call_ptr
->reply
= NULL
;
1667 log_error("Ran out of memory trying to construct method return");
1670 static void get_app_properties1(struct cdbus_method_call
* call_ptr
)
1672 get_app_properties_multiversion(call_ptr
, 1);
1675 static void get_app_properties2(struct cdbus_method_call
* call_ptr
)
1677 get_app_properties_multiversion(call_ptr
, 2);
1680 static void set_app_properties_multiversion(struct cdbus_method_call
* call_ptr
, int version
)
1683 dbus_bool_t terminal
;
1685 const char * commandline
;
1686 const char * level_str
;
1690 struct ladish_app
* app_ptr
;
1692 char * commandline_buffer
;
1697 level_type
= DBUS_TYPE_BYTE
;
1698 level_ptr
= &level_byte
;
1702 ASSERT(version
== 2);
1703 level_type
= DBUS_TYPE_STRING
;
1704 level_ptr
= &level_str
;
1707 if (!dbus_message_get_args(
1709 &cdbus_g_dbus_error
,
1710 DBUS_TYPE_UINT64
, &id
,
1711 DBUS_TYPE_STRING
, &name
,
1712 DBUS_TYPE_STRING
, &commandline
,
1713 DBUS_TYPE_BOOLEAN
, &terminal
,
1714 level_type
, level_ptr
,
1717 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1718 dbus_error_free(&cdbus_g_dbus_error
);
1726 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "invalid integer level %"PRIu8
, level_byte
);
1730 level_str
= level_byte
== 0 ? LADISH_APP_LEVEL_0
: LADISH_APP_LEVEL_1
;
1731 len
= strlen(level_str
);
1735 ASSERT(version
== 2);
1736 if (!ladish_check_app_level_validity(level_str
, &len
))
1738 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "invalid level '%s'", level_str
);
1743 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
1744 if (app_ptr
== NULL
)
1746 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
1750 if (app_ptr
->pid
!= 0 && strcmp(commandline
, app_ptr
->commandline
) != 0)
1752 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "Cannot change commandline when app is running. '%s' -> '%s'", app_ptr
->commandline
, commandline
);
1756 if (app_ptr
->pid
!= 0 && ((app_ptr
->terminal
&& !terminal
) || (!app_ptr
->terminal
&& terminal
)))
1758 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "Cannot change whether to run in terminal when app is running");
1762 if (app_ptr
->pid
!= 0 && strcmp(app_ptr
->level
, level_str
) != 0)
1764 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "Cannot change app level when app is running");
1768 if (strcmp(commandline
, app_ptr
->commandline
) != 0)
1770 commandline_buffer
= strdup(commandline
);
1771 if (commandline_buffer
== NULL
)
1773 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "strdup() failed for app commandline");
1779 commandline_buffer
= NULL
;
1782 if (strcmp(name
, app_ptr
->name
) != 0)
1784 name_buffer
= strdup(name
);
1785 if (name_buffer
== NULL
)
1787 cdbus_error(call_ptr
, DBUS_ERROR_FAILED
, "strdup() failed for app nam");
1788 if (commandline_buffer
!= NULL
)
1790 free(commandline_buffer
);
1800 if (name_buffer
!= NULL
)
1802 supervisor_ptr
->on_app_renamed(supervisor_ptr
->on_app_renamed_context
, app_ptr
->uuid
, app_ptr
->name
, name_buffer
);
1803 free(app_ptr
->name
);
1804 app_ptr
->name
= name_buffer
;
1807 if (commandline_buffer
!= NULL
)
1809 free(app_ptr
->commandline
);
1810 app_ptr
->commandline
= commandline_buffer
;
1813 memcpy(app_ptr
->level
, level_str
, len
+ 1);
1814 app_ptr
->terminal
= terminal
;
1816 emit_app_state_changed(supervisor_ptr
, app_ptr
);
1818 cdbus_method_return_new_void(call_ptr
);
1821 static void set_app_properties1(struct cdbus_method_call
* call_ptr
)
1823 set_app_properties_multiversion(call_ptr
, 1);
1826 static void set_app_properties2(struct cdbus_method_call
* call_ptr
)
1828 set_app_properties_multiversion(call_ptr
, 2);
1832 static void remove_app(struct cdbus_method_call
* call_ptr
)
1836 if (!dbus_message_get_args(
1838 &cdbus_g_dbus_error
,
1839 DBUS_TYPE_UINT64
, &id
,
1842 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1843 dbus_error_free(&cdbus_g_dbus_error
);
1847 if (ladish_command_remove_app(call_ptr
, ladish_studio_get_cmd_queue(), supervisor_ptr
->opath
, id
))
1849 cdbus_method_return_new_void(call_ptr
);
1853 static void is_app_running(struct cdbus_method_call
* call_ptr
)
1856 struct ladish_app
* app_ptr
;
1857 dbus_bool_t running
;
1859 if (!dbus_message_get_args(
1861 &cdbus_g_dbus_error
,
1862 DBUS_TYPE_UINT64
, &id
,
1865 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "Invalid arguments to method \"%s\": %s", call_ptr
->method_name
, cdbus_g_dbus_error
.message
);
1866 dbus_error_free(&cdbus_g_dbus_error
);
1870 app_ptr
= ladish_app_supervisor_find_app_by_id_internal(supervisor_ptr
, id
);
1871 if (app_ptr
== NULL
)
1873 cdbus_error(call_ptr
, DBUS_ERROR_INVALID_ARGS
, "App with ID %"PRIu64
" not found", id
);
1877 running
= app_ptr
->pid
!= 0;
1879 cdbus_method_return_new_single(call_ptr
, DBUS_TYPE_BOOLEAN
, &running
);
1882 #undef supervisor_ptr
1884 CDBUS_METHOD_ARGS_BEGIN(GetInterfaceVersion
, "Get version of this D-Bus interface")
1885 CDBUS_METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_UINT32_AS_STRING
, "Interface version")
1886 CDBUS_METHOD_ARGS_END
1888 CDBUS_METHOD_ARGS_BEGIN(GetAll
, "Get list of apps")
1889 CDBUS_METHOD_ARG_DESCRIBE_OUT("list_version", DBUS_TYPE_UINT64_AS_STRING
, "Version of the list")
1890 CDBUS_METHOD_ARG_DESCRIBE_OUT("apps_list", "a(tsbby)", "List of apps")
1891 CDBUS_METHOD_ARGS_END
1893 CDBUS_METHOD_ARGS_BEGIN(GetAll2
, "Get list of apps")
1894 CDBUS_METHOD_ARG_DESCRIBE_OUT("list_version", DBUS_TYPE_UINT64_AS_STRING
, "Version of the list")
1895 CDBUS_METHOD_ARG_DESCRIBE_OUT("apps_list", "a(tsbbs)", "List of apps")
1896 CDBUS_METHOD_ARGS_END
1898 CDBUS_METHOD_ARGS_BEGIN(RunCustom
, "Start application by supplying commandline")
1899 CDBUS_METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1900 CDBUS_METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1901 CDBUS_METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "Name")
1902 CDBUS_METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1903 CDBUS_METHOD_ARGS_END
1905 CDBUS_METHOD_ARGS_BEGIN(RunCustom2
, "Start application by supplying commandline")
1906 CDBUS_METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1907 CDBUS_METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1908 CDBUS_METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "Name")
1909 CDBUS_METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_STRING_AS_STRING
, "Level")
1910 CDBUS_METHOD_ARGS_END
1912 CDBUS_METHOD_ARGS_BEGIN(StartApp
, "Start application")
1913 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1914 CDBUS_METHOD_ARGS_END
1916 CDBUS_METHOD_ARGS_BEGIN(StopApp
, "Stop application")
1917 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1918 CDBUS_METHOD_ARGS_END
1920 CDBUS_METHOD_ARGS_BEGIN(KillApp
, "Kill application")
1921 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1922 CDBUS_METHOD_ARGS_END
1924 CDBUS_METHOD_ARGS_BEGIN(RemoveApp
, "Remove application")
1925 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1926 CDBUS_METHOD_ARGS_END
1928 CDBUS_METHOD_ARGS_BEGIN(GetAppProperties
, "Get properties of an application")
1929 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1930 CDBUS_METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING
, "")
1931 CDBUS_METHOD_ARG_DESCRIBE_OUT("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1932 CDBUS_METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1933 CDBUS_METHOD_ARG_DESCRIBE_OUT("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1934 CDBUS_METHOD_ARG_DESCRIBE_OUT("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1935 CDBUS_METHOD_ARGS_END
1937 CDBUS_METHOD_ARGS_BEGIN(GetAppProperties2
, "Get properties of an application")
1938 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1939 CDBUS_METHOD_ARG_DESCRIBE_OUT("name", DBUS_TYPE_STRING_AS_STRING
, "")
1940 CDBUS_METHOD_ARG_DESCRIBE_OUT("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1941 CDBUS_METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1942 CDBUS_METHOD_ARG_DESCRIBE_OUT("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1943 CDBUS_METHOD_ARG_DESCRIBE_OUT("level", DBUS_TYPE_STRING_AS_STRING
, "Level")
1944 CDBUS_METHOD_ARGS_END
1946 CDBUS_METHOD_ARGS_BEGIN(SetAppProperties
, "Set properties of an application")
1947 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1948 CDBUS_METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "")
1949 CDBUS_METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1950 CDBUS_METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1951 CDBUS_METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1952 CDBUS_METHOD_ARGS_END
1954 CDBUS_METHOD_ARGS_BEGIN(SetAppProperties2
, "Set properties of an application")
1955 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1956 CDBUS_METHOD_ARG_DESCRIBE_IN("name", DBUS_TYPE_STRING_AS_STRING
, "")
1957 CDBUS_METHOD_ARG_DESCRIBE_IN("commandline", DBUS_TYPE_STRING_AS_STRING
, "Commandline")
1958 CDBUS_METHOD_ARG_DESCRIBE_IN("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1959 CDBUS_METHOD_ARG_DESCRIBE_IN("level", DBUS_TYPE_STRING_AS_STRING
, "Level")
1960 CDBUS_METHOD_ARGS_END
1962 CDBUS_METHOD_ARGS_BEGIN(IsAppRunning
, "Check whether application is running")
1963 CDBUS_METHOD_ARG_DESCRIBE_IN("id", DBUS_TYPE_UINT64_AS_STRING
, "id of app")
1964 CDBUS_METHOD_ARG_DESCRIBE_OUT("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether app is running")
1965 CDBUS_METHOD_ARGS_END
1969 CDBUS_METHOD_DESCRIBE(GetInterfaceVersion
, get_version
) /* sync */
1970 CDBUS_METHOD_DESCRIBE(GetAll
, get_all1
) /* sync */
1971 CDBUS_METHOD_DESCRIBE(GetAll2
, get_all2
) /* sync */
1972 CDBUS_METHOD_DESCRIBE(RunCustom
, run_custom1
) /* async */
1973 CDBUS_METHOD_DESCRIBE(RunCustom2
, run_custom2
) /* async */
1974 CDBUS_METHOD_DESCRIBE(StartApp
, start_app
) /* async */
1975 CDBUS_METHOD_DESCRIBE(StopApp
, stop_app
) /* async */
1976 CDBUS_METHOD_DESCRIBE(KillApp
, kill_app
) /* async */
1977 CDBUS_METHOD_DESCRIBE(GetAppProperties
, get_app_properties1
) /* sync */
1978 CDBUS_METHOD_DESCRIBE(GetAppProperties2
, get_app_properties2
) /* sync */
1979 CDBUS_METHOD_DESCRIBE(SetAppProperties
, set_app_properties1
) /* sync */
1980 CDBUS_METHOD_DESCRIBE(SetAppProperties2
, set_app_properties2
) /* sync */
1981 CDBUS_METHOD_DESCRIBE(RemoveApp
, remove_app
) /* sync */
1982 CDBUS_METHOD_DESCRIBE(IsAppRunning
, is_app_running
) /* sync */
1985 CDBUS_SIGNAL_ARGS_BEGIN(AppAdded
, "")
1986 CDBUS_SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
1987 CDBUS_SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
1988 CDBUS_SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
1989 CDBUS_SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1990 CDBUS_SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
1991 CDBUS_SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
1992 CDBUS_SIGNAL_ARGS_END
1994 CDBUS_SIGNAL_ARGS_BEGIN(AppAdded2
, "")
1995 CDBUS_SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
1996 CDBUS_SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
1997 CDBUS_SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
1998 CDBUS_SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
1999 CDBUS_SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
2000 CDBUS_SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_STRING_AS_STRING
, "Level")
2001 CDBUS_SIGNAL_ARGS_END
2003 CDBUS_SIGNAL_ARGS_BEGIN(AppRemoved
, "")
2004 CDBUS_SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
2005 CDBUS_SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
2006 CDBUS_SIGNAL_ARGS_END
2008 CDBUS_SIGNAL_ARGS_BEGIN(AppStateChanged
, "")
2009 CDBUS_SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
2010 CDBUS_SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
2011 CDBUS_SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
2012 CDBUS_SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
2013 CDBUS_SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
2014 CDBUS_SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_BYTE_AS_STRING
, "Level")
2015 CDBUS_SIGNAL_ARGS_END
2017 CDBUS_SIGNAL_ARGS_BEGIN(AppStateChanged2
, "")
2018 CDBUS_SIGNAL_ARG_DESCRIBE("new_list_version", DBUS_TYPE_UINT64_AS_STRING
, "")
2019 CDBUS_SIGNAL_ARG_DESCRIBE("id", DBUS_TYPE_UINT64_AS_STRING
, "")
2020 CDBUS_SIGNAL_ARG_DESCRIBE("name", DBUS_TYPE_STRING_AS_STRING
, "")
2021 CDBUS_SIGNAL_ARG_DESCRIBE("running", DBUS_TYPE_BOOLEAN_AS_STRING
, "")
2022 CDBUS_SIGNAL_ARG_DESCRIBE("terminal", DBUS_TYPE_BOOLEAN_AS_STRING
, "Whether to run in terminal")
2023 CDBUS_SIGNAL_ARG_DESCRIBE("level", DBUS_TYPE_STRING_AS_STRING
, "Level")
2024 CDBUS_SIGNAL_ARGS_END
2027 CDBUS_SIGNAL_DESCRIBE(AppAdded
)
2028 CDBUS_SIGNAL_DESCRIBE(AppAdded2
)
2029 CDBUS_SIGNAL_DESCRIBE(AppRemoved
)
2030 CDBUS_SIGNAL_DESCRIBE(AppStateChanged
)
2031 CDBUS_SIGNAL_DESCRIBE(AppStateChanged2
)
2034 CDBUS_INTERFACE_DEFAULT_HANDLER_METHODS_AND_SIGNALS(g_iface_app_supervisor
, IFACE_APP_SUPERVISOR
)