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
lease->object_ids[lease->nobject_ids++] = connector->connector_id;
lease->is_granted = false;
lease->object_ids[lease->nobject_ids++] = connector->connector_id;
lease->is_granted = false;
assert(lm);
for (int i = 0; i < lm->nleases; i++) {
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]);
}
lease_free(lm->leases[i]);
}
drmModeCreateLease(lm->drm_fd, lease->object_ids,
lease->nobject_ids, 0, &lease->lessee_id);
drmModeCreateLease(lm->drm_fd, lease->object_ids,
lease->nobject_ids, 0, &lease->lessee_id);
- if (lease->lease_fd < 0) {
ERROR_LOG("drmModeCreateLease failed on lease %s: %s\n",
lease->base.name, strerror(errno));
return -1;
}
lease->is_granted = true;
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)
}
int lm_lease_transfer(struct lm *lm, struct lease_handle *handle)
if (!lease->is_granted)
return -1;
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) {
lm_lease_revoke(lm, handle);
if (lm_lease_grant(lm, handle) < 0) {
+ lm_lease_close(handle);
- close_after_lease_transition(lease, old_lease_fd);
return lease->lease_fd;
}
return lease->lease_fd;
}
drmModeRevokeLease(lm->drm_fd, lease->lessee_id);
cancel_lease_transition_thread(lease);
drmModeRevokeLease(lm->drm_fd, lease->lessee_id);
cancel_lease_transition_thread(lease);
- close(lease->lease_fd);
lease->is_granted = false;
}
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;
+}
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);
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);
request = parse_client_request(sock);
if (request < 0 && (ev.events & POLLHUP))
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;
struct ls_client *client = sock->client;
struct ls_server *server = client->serv;
enum ls_req_type {
LS_REQ_GET_LEASE,
LS_REQ_RELEASE_LEASE,
enum ls_req_type {
LS_REQ_GET_LEASE,
LS_REQ_RELEASE_LEASE,
+ LS_REQ_CLIENT_DISCONNECT,
"Options:\n"
"-h, --help \tPrint this help\n"
"-v, --verbose \tEnable verbose debug messages\n"
"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",
-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'},
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'},
bool debug_log = false;
bool can_transfer_leases = false;
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) {
int c;
while ((c = getopt_long(argc, argv, opts, options, NULL)) != -1) {
case 't':
can_transfer_leases = true;
break;
case 't':
can_transfer_leases = true;
break;
+ case 'k':
+ keep_on_crash = true;
+ break;
case 'h':
ret = EXIT_SUCCESS;
/* fall through */
case 'h':
ret = EXIT_SUCCESS;
/* fall through */
break;
}
case LS_REQ_RELEASE_LEASE:
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);
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");
break;
default:
ERROR_LOG("Internal error: Invalid lease request\n");