summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-03-26 23:40:25 +0100
committerwm4 <wm4@nowhere>2020-03-26 23:40:25 +0100
commit9bda301eb4d8aa75d435f24146c3a66ab74cafea (patch)
treef2d9fc03c108fdfc2ede50f91ac4468b7af88530
parentca3492213035ac6299fc54803520ee9427595181 (diff)
downloadmpv-9bda301eb4d8aa75d435f24146c3a66ab74cafea.tar.bz2
mpv-9bda301eb4d8aa75d435f24146c3a66ab74cafea.tar.xz
command: use client IDs for hooks
Removes weird potential race conditions when a client is removed and a new one with the same name is created.
-rw-r--r--player/client.c12
-rw-r--r--player/client.h1
-rw-r--r--player/command.c17
-rw-r--r--player/command.h6
4 files changed, 24 insertions, 12 deletions
diff --git a/player/client.c b/player/client.c
index 41645b5d95..a72cb0125f 100644
--- a/player/client.c
+++ b/player/client.c
@@ -262,6 +262,14 @@ bool mp_client_exists(struct MPContext *mpctx, const char *client_name)
return r;
}
+bool mp_client_id_exists(struct MPContext *mpctx, int64_t id)
+{
+ pthread_mutex_lock(&mpctx->clients->lock);
+ bool r = find_client_id(mpctx->clients, id);
+ pthread_mutex_unlock(&mpctx->clients->lock);
+ return r;
+}
+
struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name)
{
pthread_mutex_lock(&clients->lock);
@@ -1825,7 +1833,7 @@ int mpv_hook_add(mpv_handle *ctx, uint64_t reply_userdata,
const char *name, int priority)
{
lock_core(ctx);
- mp_hook_add(ctx->mpctx, ctx->name, name, reply_userdata, priority);
+ mp_hook_add(ctx->mpctx, ctx->name, ctx->id, name, reply_userdata, priority);
unlock_core(ctx);
return 0;
}
@@ -1833,7 +1841,7 @@ int mpv_hook_add(mpv_handle *ctx, uint64_t reply_userdata,
int mpv_hook_continue(mpv_handle *ctx, uint64_t id)
{
lock_core(ctx);
- int r = mp_hook_continue(ctx->mpctx, ctx->name, id);
+ int r = mp_hook_continue(ctx->mpctx, ctx->id, id);
unlock_core(ctx);
return r;
}
diff --git a/player/client.h b/player/client.h
index a8eae2d0c1..47af084cc5 100644
--- a/player/client.h
+++ b/player/client.h
@@ -24,6 +24,7 @@ bool mp_is_shutting_down(struct MPContext *mpctx);
bool mp_clients_all_initialized(struct MPContext *mpctx);
bool mp_client_exists(struct MPContext *mpctx, const char *client_name);
+bool mp_client_id_exists(struct MPContext *mpctx, int64_t id);
void mp_client_broadcast_event(struct MPContext *mpctx, int event, void *data);
int mp_client_send_event(struct MPContext *mpctx, const char *client_name,
uint64_t reply_userdata, int event, void *data);
diff --git a/player/command.c b/player/command.c
index 5984d6c5b3..3098e1d9bf 100644
--- a/player/command.c
+++ b/player/command.c
@@ -118,7 +118,8 @@ struct overlay {
};
struct hook_handler {
- char *client; // client API user name
+ char *client; // client mpv_handle name (for logging)
+ int64_t client_id; // client mpv_handle ID
char *type; // kind of hook, e.g. "on_load"
uint64_t user_id; // user-chosen ID
int priority; // priority for global hook order
@@ -160,7 +161,7 @@ bool mp_hook_test_completion(struct MPContext *mpctx, char *type)
for (int n = 0; n < cmd->num_hooks; n++) {
struct hook_handler *h = cmd->hooks[n];
if (h->active && strcmp(h->type, type) == 0) {
- if (!mp_client_exists(mpctx, h->client)) {
+ if (!mp_client_id_exists(mpctx, h->client_id)) {
MP_WARN(mpctx, "client removed during hook handling\n");
hook_remove(mpctx, h);
break;
@@ -183,7 +184,8 @@ static int invoke_hook_handler(struct MPContext *mpctx, struct hook_handler *h)
.id = h->seq,
},
reply_id = h->user_id;
- int r = mp_client_send_event(mpctx, h->client, reply_id, MPV_EVENT_HOOK, m);
+ char *name = mp_tprintf(22, "@%"PRIi64, h->client_id);
+ int r = mp_client_send_event(mpctx, name, reply_id, MPV_EVENT_HOOK, m);
if (r < 0) {
MP_WARN(mpctx, "Sending hook command failed. Removing hook.\n");
hook_remove(mpctx, h);
@@ -216,13 +218,13 @@ void mp_hook_start(struct MPContext *mpctx, char *type)
}
}
-int mp_hook_continue(struct MPContext *mpctx, char *client, uint64_t id)
+int mp_hook_continue(struct MPContext *mpctx, int64_t client_id, uint64_t id)
{
struct command_ctx *cmd = mpctx->command_ctx;
for (int n = 0; n < cmd->num_hooks; n++) {
struct hook_handler *h = cmd->hooks[n];
- if (strcmp(h->client, client) == 0 && h->seq == id) {
+ if (h->client_id == client_id && h->seq == id) {
if (!h->active)
break;
h->active = false;
@@ -243,14 +245,15 @@ static int compare_hook(const void *pa, const void *pb)
return (*h1)->seq - (*h2)->seq;
}
-void mp_hook_add(struct MPContext *mpctx, const char *client, const char *name,
- uint64_t user_id, int pri)
+void mp_hook_add(struct MPContext *mpctx, char *client, int64_t client_id,
+ const char *name, uint64_t user_id, int pri)
{
struct command_ctx *cmd = mpctx->command_ctx;
struct hook_handler *h = talloc_ptrtype(cmd, h);
int64_t seq = ++cmd->hook_seq;
*h = (struct hook_handler){
.client = talloc_strdup(h, client),
+ .client_id = client_id,
.type = talloc_strdup(h, name),
.user_id = user_id,
.priority = pri,
diff --git a/player/command.h b/player/command.h
index 1b3154394a..17e0726b0b 100644
--- a/player/command.h
+++ b/player/command.h
@@ -105,9 +105,9 @@ enum {
bool mp_hook_test_completion(struct MPContext *mpctx, char *type);
void mp_hook_start(struct MPContext *mpctx, char *type);
-int mp_hook_continue(struct MPContext *mpctx, char *client, uint64_t id);
-void mp_hook_add(struct MPContext *mpctx, const char *client, const char *name,
- uint64_t user_id, int pri);
+int mp_hook_continue(struct MPContext *mpctx, int64_t client_id, uint64_t id);
+void mp_hook_add(struct MPContext *mpctx, char *client, int64_t client_id,
+ const char *name, uint64_t user_id, int pri);
void mark_seek(struct MPContext *mpctx);