hs-proxy,hs-clientmanager: Handle correctly the shutdown of apps 45/26045/3
authorMarius Vlad <marius.vlad@collabora.com>
Mon, 15 Feb 2021 15:50:30 +0000 (17:50 +0200)
committerMarius Vlad <marius.vlad@collabora.com>
Wed, 3 Mar 2021 14:50:07 +0000 (16:50 +0200)
The fake subscribe mechanism failed to account for the client context,
which is bound to the afb_req_t of the client itself, and only
dealing with the client list.  This effectively means we can't
really register (a/an automated) callback function to remove the
appid from the client list once the application has been legally
terminated/stopped.

This adds a check to verify, for the showWindow verb, if the application
is still found to be running, and return the appropriate value in case
that is not case. This should determine to start the application and fix
the issue.

Bug-AGL: SPEC-3796

Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: Ia828e1ec374bf3bed21c52814721074c01f16691

src/hs-clientmanager.cpp
src/hs-proxy.cpp
src/hs-proxy.h

index e880c62..8f02953 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <cstring>
 #include <algorithm>
+#include <cassert>
+#include "hs-proxy.h"
 #include "hs-clientmanager.h"
 
 static const char _homescreen[] = "homescreen";
@@ -158,6 +160,46 @@ void HS_ClientManager::removeClientCtxt(void *data)
     appid2ctxt.erase(ctxt->id);
 }
 
+static int
+is_application_running(afb_req_t request, std::string id)
+{
+    bool app_still_running = false;
+    struct json_object *jobj = nullptr;
+
+    HS_AfmMainProxy afm_proxy;
+
+    // note this is sync, so this might block if afm-system-daemon is down
+    afm_proxy.ps(request->api, &jobj);
+
+    if (jobj) {
+           const int len = json_object_array_length(jobj);
+           for (int i = 0; i < len; i++) {
+               struct json_object *aid;
+               struct json_object *item =
+                   json_object_array_get_idx(jobj, i);
+
+               bool isFound = json_object_object_get_ex(item, "id", &aid);
+               if (isFound) {
+                   const char *str_appid = json_object_get_string(aid);
+                   if (strcmp(str_appid, id.c_str()) == 0) {
+                       app_still_running = true;
+                       break;
+                   }
+               }
+           }
+    }
+
+    if (!app_still_running) {
+        // we don't remove it from the context list as we're haven't really subscribed,
+        // and we just need to remove it from client_list, which happens here. We also
+       // return AFB_REQ_NOT_STARTED_APPLICATION which will attempt to start it (again).
+        HS_ClientManager::instance()->removeClient(id);
+        return AFB_REQ_NOT_STARTED_APPLICATION;
+    }
+
+    return 0;
+}
+
 /**
  * handle homescreen request
  *
@@ -184,8 +226,21 @@ int HS_ClientManager::handleRequest(afb_req_t request, const char *verb, const c
     else {
         std::string id(appid);
         auto ip = client_list.find(id);
-        if(ip != client_list.end()) {
-           // FIXME: do another verification here in case the application died
+       if(ip != client_list.end()) {
+           // for showWindow verb we need to verify if the app is (still)
+           // running, and return the appropriate value to attempt to start it
+           // again. This 'problem' is avoided if the application itself
+           // subscribes and with that process, to install a callback that
+           // automatically removes the application from client_list.
+           // That is exactly how "subscribe" verb is handled below.
+            if (strcasecmp(verb, "showWindow") == 0) {
+                ret = is_application_running(request, id);
+                if (ret == AFB_REQ_NOT_STARTED_APPLICATION) {
+                    AFB_INFO("%s is not running. Will attempt to start it");
+                    return ret;
+                }
+            }
+            AFB_INFO("%s found to be running. Forwarding request to the client");
             ret = ip->second->handleRequest(request, verb);
         }
         else {
index 7571dad..f8b796c 100644 (file)
@@ -56,6 +56,7 @@ static void api_callback(void *closure, struct json_object *object, const char *
 
     /* if we have an error then we couldn't start the application so we remove it */
     if (error) {
+          AFB_INFO("asynchronous call, removing client %s", cdata->appid);
            clientManager->removeClient(cdata->appid);
     }
 
@@ -121,6 +122,23 @@ int HS_AfmMainProxy::runnables(afb_api_t api, struct json_object **object)
     return api_call_sync(api, _afm_main, __FUNCTION__, nullptr, object);
 }
 
+/**
+ * get running application list
+ *
+ * #### Parameters
+ *  - api : the api serving the request
+ *  - object : return the details of appid
+ *
+ * #### Return
+ *  0 : success
+ *  1 : fail
+ *
+ */
+int HS_AfmMainProxy::ps(afb_api_t api, struct json_object **object)
+{
+    return api_call_sync(api, _afm_main, "runners", nullptr, object);
+}
+
 /**
  * get details of application
  *
index 4016032..a70bfa1 100644 (file)
@@ -25,6 +25,7 @@
 struct HS_AfmMainProxy {
     // synchronous call, call result in object
     int runnables(afb_api_t api, struct json_object **object);
+    int ps(afb_api_t api, struct json_object **object);
     int detail(afb_api_t api, const std::string &id, struct json_object **object);
 
     // asynchronous call, reply in callback function