Add option to hold lease on unexpected disconnect 38/26238/1
authorDamian Hobson-Garcia <dhobsong@igel.co.jp>
Mon, 22 Mar 2021 02:54:16 +0000 (11:54 +0900)
committerDamian Hobson-Garcia <dhobsong@igel.co.jp>
Tue, 6 Apr 2021 06:58:47 +0000 (15:58 +0900)
If a client application crashes while owning a lease,
the lease will automatically be revoked and all references
freed to make it available for another (or the restarted
original) client to claim and continue display.  This will
cause the screen to blank while the lease is unowned.

Add an option to revoke the lease, but keep the reference to
the lease descriptor, so that the screen does not blank while
unowned.

This only has effect when a client exits without calling the
`dlm_release_lease` function. Otherwise the lease is revoked
and the descriptor dereferenced, just as before.

Bug-AGL: SPEC-3862

Signed-off-by: Damian Hobson-Garcia <dhobsong@igel.co.jp>
Change-Id: I3fc2c8fde4118b6e298ba31807fd5fa4766a97dd

drm-lease-manager/lease-manager.c
drm-lease-manager/lease-manager.h
drm-lease-manager/lease-server.c
drm-lease-manager/lease-server.h
drm-lease-manager/main.c

index 5d79b8d..cfb1ab5 100644 (file)
@@ -331,6 +331,7 @@ static struct lease *lease_create(struct lm *lm, drmModeConnectorPtr connector)
        lease->object_ids[lease->nobject_ids++] = connector->connector_id;
 
        lease->is_granted = false;
+       lease->lease_fd = -1;
 
        return lease;
 
@@ -417,7 +418,9 @@ void lm_destroy(struct lm *lm)
        assert(lm);
 
        for (int i = 0; i < lm->nleases; i++) {
-               lm_lease_revoke(lm, (struct lease_handle *)lm->leases[i]);
+               struct lease_handle *lease_handle = &lm->leases[i]->base;
+               lm_lease_revoke(lm, lease_handle);
+               lm_lease_close(lease_handle);
                lease_free(lm->leases[i]);
        }
 
@@ -448,17 +451,24 @@ int lm_lease_grant(struct lm *lm, struct lease_handle *handle)
                return -1;
        }
 
-       lease->lease_fd =
+       int lease_fd =
            drmModeCreateLease(lm->drm_fd, lease->object_ids,
                               lease->nobject_ids, 0, &lease->lessee_id);
-       if (lease->lease_fd < 0) {
+       if (lease_fd < 0) {
                ERROR_LOG("drmModeCreateLease failed on lease %s: %s\n",
                          lease->base.name, strerror(errno));
                return -1;
        }
 
        lease->is_granted = true;
-       return lease->lease_fd;
+
+       int old_lease_fd = lease->lease_fd;
+       lease->lease_fd = lease_fd;
+
+       if (old_lease_fd >= 0)
+               close_after_lease_transition(lease, old_lease_fd);
+
+       return lease_fd;
 }
 
 int lm_lease_transfer(struct lm *lm, struct lease_handle *handle)
@@ -470,15 +480,12 @@ int lm_lease_transfer(struct lm *lm, struct lease_handle *handle)
        if (!lease->is_granted)
                return -1;
 
-       int old_lease_fd = dup(lease->lease_fd);
-
        lm_lease_revoke(lm, handle);
        if (lm_lease_grant(lm, handle) < 0) {
-               close(old_lease_fd);
+               lm_lease_close(handle);
                return -1;
        }
 
-       close_after_lease_transition(lease, old_lease_fd);
        return lease->lease_fd;
 }
 
@@ -494,6 +501,14 @@ void lm_lease_revoke(struct lm *lm, struct lease_handle *handle)
 
        drmModeRevokeLease(lm->drm_fd, lease->lessee_id);
        cancel_lease_transition_thread(lease);
-       close(lease->lease_fd);
        lease->is_granted = false;
 }
+
+void lm_lease_close(struct lease_handle *handle)
+{
+       assert(handle);
+
+       struct lease *lease = (struct lease *)handle;
+       close(lease->lease_fd);
+       lease->lease_fd = -1;
+}
index 581e05c..55bf81e 100644 (file)
@@ -27,4 +27,5 @@ int lm_get_lease_handles(struct lm *lm, struct lease_handle ***lease_handles);
 int lm_lease_grant(struct lm *lm, struct lease_handle *lease_handle);
 int lm_lease_transfer(struct lm *lm, struct lease_handle *lease_handle);
 void lm_lease_revoke(struct lm *lm, struct lease_handle *lease_handle);
+void lm_lease_close(struct lease_handle *lease_handle);
 #endif
index c81d363..a7e3190 100644 (file)
@@ -329,7 +329,7 @@ bool ls_get_request(struct ls *ls, struct ls_req *req)
                        request = parse_client_request(sock);
 
                if (request < 0 && (ev.events & POLLHUP))
-                       request = LS_REQ_RELEASE_LEASE;
+                       request = LS_REQ_CLIENT_DISCONNECT;
 
                struct ls_client *client = sock->client;
                struct ls_server *server = client->serv;
index 1aaad30..823d340 100644 (file)
@@ -24,6 +24,7 @@ struct ls_client;
 enum ls_req_type {
        LS_REQ_GET_LEASE,
        LS_REQ_RELEASE_LEASE,
+       LS_REQ_CLIENT_DISCONNECT,
 };
 
 struct ls_req {
index 78ff0df..2927253 100644 (file)
@@ -28,15 +28,17 @@ static void usage(const char *progname)
               "Options:\n"
               "-h, --help \tPrint this help\n"
               "-v, --verbose \tEnable verbose debug messages\n"
-              "-t, --lease-transfer \tAllow lease transfter to new clients\n",
+              "-t, --lease-transfer \tAllow lease transfter to new clients\n"
+              "-k, --keep-on-crash \tDon't close lease on client crash\n",
               progname);
 }
 
-const char *opts = "vth";
+const char *opts = "vtkh";
 const struct option options[] = {
     {"help", no_argument, NULL, 'h'},
     {"verbose", no_argument, NULL, 'v'},
     {"lease-transfer", no_argument, NULL, 't'},
+    {"keep-on-crash", no_argument, NULL, 'k'},
     {NULL, 0, NULL, 0},
 };
 
@@ -46,6 +48,7 @@ int main(int argc, char **argv)
 
        bool debug_log = false;
        bool can_transfer_leases = false;
+       bool keep_on_crash = false;
 
        int c;
        while ((c = getopt_long(argc, argv, opts, options, NULL)) != -1) {
@@ -57,6 +60,9 @@ int main(int argc, char **argv)
                case 't':
                        can_transfer_leases = true;
                        break;
+               case 'k':
+                       keep_on_crash = true;
+                       break;
                case 'h':
                        ret = EXIT_SUCCESS;
                        /* fall through */
@@ -122,9 +128,14 @@ int main(int argc, char **argv)
                        break;
                }
                case LS_REQ_RELEASE_LEASE:
+               case LS_REQ_CLIENT_DISCONNECT:
                        ls_disconnect_client(ls, req.client);
                        req.lease_handle->user_data = NULL;
                        lm_lease_revoke(lm, req.lease_handle);
+
+                       if (!keep_on_crash || req.type == LS_REQ_RELEASE_LEASE)
+                               lm_lease_close(req.lease_handle);
+
                        break;
                default:
                        ERROR_LOG("Internal error: Invalid lease request\n");