afm-run: handles pids and terminates groups
[src/app-framework-main.git] / src / afm-run.c
index f28849a..360f29d 100644 (file)
 
 #include "verbose.h"
 #include "utils-dir.h"
-#include "afm-run.h"
+#include "utils-json.h"
+#include "afm-launch-mode.h"
 #include "afm-launch.h"
+#include "afm-run.h"
 
 enum appstate {
        as_starting,
@@ -64,6 +66,7 @@ static char *homeappdir;
 
 /****************** manages pgids **********************/
 
+#if 0
 /* get a runner by its pgid */
 static struct apprun *runner_of_pgid(pid_t pgid)
 {
@@ -72,6 +75,7 @@ static struct apprun *runner_of_pgid(pid_t pgid)
                result = result->next_by_pgid;
        return result;
 }
+#endif
 
 /* insert a runner for its pgid */
 static void pgid_insert(struct apprun *runner)
@@ -94,14 +98,14 @@ static void pgid_remove(struct apprun *runner)
 /* get a runner by its pid */
 static struct apprun *runner_of_pid(pid_t pid)
 {
-       /* try avoiding system call */
-       struct apprun *result = runner_of_pgid(pid);
-       if (result == NULL) {
-               result = runner_of_pgid(getpgid(pid));
-               if (result && result->pids[1] != pid)
-                       result = NULL;
-       }
-       return result;
+       int i;
+       struct apprun *result;
+
+       for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++)
+               for (result = runners_by_pgid[i] ; result != NULL ; result = result->next_by_pgid)
+                       if (result->pids[0] == pid || result->pids[1] == pid)
+                               return result;
+       return NULL;
 }
 
 /****************** manages runners (by runid) **********************/
@@ -213,7 +217,7 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctxt)
 {
        struct apprun *runner;
 
-       runner = runner_of_pgid(info->si_pid);
+       runner = runner_of_pid(info->si_pid);
        if (!runner)
                return;
 
@@ -224,6 +228,7 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctxt)
        case CLD_TRAPPED:
                runner->state = as_terminated;
                pgid_remove(runner);
+               killpg(runner->pids[0], SIGKILL);
                break;
 
        case CLD_STOPPED:
@@ -238,35 +243,21 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctxt)
 
 /**************** handle afm_launch_desc *********************/
 
-static int get_jstr(struct json_object *obj, const char *key, const char **value)
-{
-       json_object *data;
-       return json_object_object_get_ex(obj, key, &data)
-               && json_object_get_type(data) == json_type_string
-               && (*value = json_object_get_string(data)) != NULL;
-}
-
-static int get_jint(struct json_object *obj, const char *key, int *value)
-{
-       json_object *data;
-       return json_object_object_get_ex(obj, key, &data)
-               && json_object_get_type(data) == json_type_int
-               && ((*value = (int)json_object_get_int(data)), 1);
-}
-
-static int fill_launch_desc(struct json_object *appli, struct afm_launch_desc *desc)
+static int fill_launch_desc(struct json_object *appli, enum afm_launch_mode mode, struct afm_launch_desc *desc)
 {
        json_object *pub;
 
+       assert(launch_mode_is_valid(mode));
+
        /* main items */
-       if(!json_object_object_get_ex(appli, "public", &pub)
-       || !get_jstr(appli, "path", &desc->path)
-       || !get_jstr(appli, "id", &desc->tag)
-       || !get_jstr(appli, "content", &desc->content)
-       || !get_jstr(appli, "type", &desc->type)
-       || !get_jstr(pub, "name", &desc->name)
-       || !get_jint(pub, "width", &desc->width)
-       || !get_jint(pub, "height", &desc->height)) {
+       if(!j_read_object_at(appli, "public", &pub)
+       || !j_read_string_at(appli, "path", &desc->path)
+       || !j_read_string_at(appli, "id", &desc->tag)
+       || !j_read_string_at(appli, "content", &desc->content)
+       || !j_read_string_at(appli, "type", &desc->type)
+       || !j_read_string_at(pub, "name", &desc->name)
+       || !j_read_integer_at(pub, "width", &desc->width)
+       || !j_read_integer_at(pub, "height", &desc->height)) {
                errno = EINVAL;
                return -1;
        }
@@ -280,20 +271,25 @@ static int fill_launch_desc(struct json_object *appli, struct afm_launch_desc *d
 
        /* finaly */
        desc->home = homeappdir;
+       desc->mode = mode;
        return 0;
 };
 
 /**************** API handling ************************/
 
-int afm_run_start(struct json_object *appli)
+int afm_run_start(struct json_object *appli, enum afm_launch_mode mode, char **uri)
 {
        static struct apprun *runner;
        struct afm_launch_desc desc;
        int rc;
        sigset_t saved, blocked;
 
+       assert(launch_mode_is_valid(mode));
+       assert(mode == mode_local || uri != NULL);
+       assert(uri == NULL || *uri == NULL);
+
        /* prepare to launch */
-       rc = fill_launch_desc(appli, &desc);
+       rc = fill_launch_desc(appli, mode, &desc);
        if (rc)
                return rc;
        runner = createrunner(appli);
@@ -306,7 +302,7 @@ int afm_run_start(struct json_object *appli)
        sigprocmask(SIG_BLOCK, &blocked, &saved);
 
        /* launch now */
-       rc = afm_launch(&desc, runner->pids);
+       rc = afm_launch(&desc, runner->pids, uri);
        if (rc < 0) {
                /* fork failed */
                sigprocmask(SIG_SETMASK, &saved, NULL);
@@ -352,10 +348,8 @@ static json_object *mkstate(struct apprun *runner)
                goto error;
 
        /* the runid */
-       obj = json_object_new_int(runner->runid);
-       if (obj == NULL)
+       if (!j_add_integer(result, "runid", runner->runid))
                goto error2;
-       json_object_object_add(result, "runid", obj); /* TODO TEST STATUS */
 
        /* the state */
        switch(runner->state) {
@@ -370,17 +364,16 @@ static json_object *mkstate(struct apprun *runner)
                state = "terminated";
                break;
        }
-       obj = json_object_new_string(state);
-       if (obj == NULL)
+       if (!j_add_string(result, "state", state))
                goto error2;
-       json_object_object_add(result, "state", obj); /* TODO TEST STATUS */
 
        /* the application id */
        rc = json_object_object_get_ex(runner->appli, "public", &obj);
        assert(rc);
        rc = json_object_object_get_ex(obj, "id", &obj);
        assert(rc);
-       json_object_object_add(result, "id", obj); /* TODO TEST STATUS */
+       if (!j_add(result, "id", obj))
+               goto error2;
        json_object_get(obj);
 
        /* done */
@@ -401,25 +394,29 @@ struct json_object *afm_run_list()
 
        /* creates the object */
        result = json_object_new_array();
-       if (result == NULL) {
-               errno = ENOMEM;
-               return NULL;            
-       }
+       if (result == NULL)
+               goto error;
 
        for (i = 0 ; i < ROOT_RUNNERS_COUNT ; i++) {
                for (runner = runners_by_runid[i] ; runner ; runner = runner->next_by_runid) {
                        if (runner->state != as_terminating && runner->state != as_terminated) {
                                obj = mkstate(runner);
-                               if (obj == NULL) {
-                                       json_object_put(result);
-                                       return NULL;
+                               if (obj == NULL)
+                                       goto error2;
+                               if (json_object_array_add(result, obj) == -1) {
+                                       json_object_put(obj);
+                                       goto error2;
                                }
-                               /* TODO status ? */
-                               json_object_array_add(result, obj);
                        }
                }
        }
        return result;
+
+error2:
+       json_object_put(result);
+error:
+       errno = ENOMEM;
+       return NULL;
 }
 
 struct json_object *afm_run_state(int runid)
@@ -443,6 +440,11 @@ int afm_run_init()
        struct passwd passwd, *pw;
        struct sigaction siga;
 
+       /* init launcher */
+       rc = afm_launch_initialize();
+       if (rc)
+               return rc;
+
        /* computes the 'homeappdir' */
        me = geteuid();
        rc = getpwuid_r(me, &passwd, buf, sizeof buf, &pw);