aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Vlad <marius.vlad@collabora.com>2021-02-15 17:50:30 +0200
committerMarius Vlad <marius.vlad@collabora.com>2021-03-03 16:57:40 +0200
commite316917605f65a59af1435247df883f3f335ad26 (patch)
tree0dc2b391e088fd54f9225bded839d3a58126d7b8
parenta7bdb3df4c761d4856cb7eebdc32c63bbf06936f (diff)
hs-proxy,hs-clientmanager: Handle correctly the shutdown of apps
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
-rw-r--r--src/hs-clientmanager.cpp59
-rw-r--r--src/hs-proxy.cpp18
-rw-r--r--src/hs-proxy.h1
3 files changed, 76 insertions, 2 deletions
diff --git a/src/hs-clientmanager.cpp b/src/hs-clientmanager.cpp
index e880c62..8f02953 100644
--- a/src/hs-clientmanager.cpp
+++ b/src/hs-clientmanager.cpp
@@ -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 {
diff --git a/src/hs-proxy.cpp b/src/hs-proxy.cpp
index 7571dad..f8b796c 100644
--- a/src/hs-proxy.cpp
+++ b/src/hs-proxy.cpp
@@ -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);
}
@@ -122,6 +123,23 @@ int HS_AfmMainProxy::runnables(afb_api_t api, struct json_object **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
*
* #### Parameters
diff --git a/src/hs-proxy.h b/src/hs-proxy.h
index 4016032..a70bfa1 100644
--- a/src/hs-proxy.h
+++ b/src/hs-proxy.h
@@ -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