Skip to content

Commit bec968c

Browse files
mp.input: send buffer ids with logs to avoid race conditions
This commit modifies the log methods in mp.input to always send the id of the latest `input.get()` request with log entries. Previously, the log methods applied to whichever input request happened to be open when the log message was received. Even when scripts used these methods correctly, there was the risk of sending a log to the wrong log buffer if the active input request changed while the log message was in transit; a race condition. Now the id of the latest `input.get()` request is sent alongside the log messages, preventing data races between scripts while also preventing those logs from being discarded.
1 parent debb26d commit bec968c

3 files changed

Lines changed: 51 additions & 18 deletions

File tree

player/javascript/defaults.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ mp.options = { read_options: read_options };
655655
*********************************************************************/
656656
var input_handle_counter = 1;
657657
var latest_handler_id
658+
var latest_log_id
658659

659660
function register_event_handler(t) {
660661
var handler_id = "input-event/" + input_handle_counter;
@@ -686,12 +687,17 @@ function register_event_handler(t) {
686687
return handler_id;
687688
}
688689

690+
function input_request(t) {
691+
t.has_completions = t.complete !== undefined;
692+
693+
mp.commandv("script-message-to", "console", "get-input",
694+
mp.script_name, register_event_handler(t), JSON.stringify(t));
695+
}
696+
689697
mp.input = {
690698
get: function(t) {
691-
t.has_completions = t.complete !== undefined;
692-
693-
mp.commandv("script-message-to", "console", "get-input",
694-
mp.script_name, register_event_handler(t), JSON.stringify(t));
699+
latest_log_id = t.id || mp.script_name + (t.prompt || "");
700+
return input_request(t);
695701
},
696702
terminate: function () {
697703
mp.commandv("script-message-to", "console", "disable", JSON.stringify({
@@ -700,21 +706,26 @@ mp.input = {
700706
},
701707
log: function (message, style, terminal_style) {
702708
mp.commandv("script-message-to", "console", "log", JSON.stringify({
709+
log_id: latest_log_id,
703710
text: message,
704711
style: style,
705712
terminal_style: terminal_style,
706713
}));
707714
},
708715
log_error: function (message) {
709-
mp.commandv("script-message-to", "console", "log",
710-
JSON.stringify({ text: message, error: true }));
716+
mp.commandv("script-message-to", "console", "log", JSON.stringify({
717+
log_id: latest_log_id,
718+
text: message,
719+
error: true
720+
}));
711721
},
712722
set_log: function (log) {
723+
if (!latest_log_id) return;
713724
mp.commandv("script-message-to", "console", "set-log",
714-
JSON.stringify(log));
725+
JSON.stringify(log), latest_log_id);
715726
}
716727
}
717-
mp.input.select = mp.input.get
728+
mp.input.select = input_request
718729

719730
/**********************************************************************
720731
* various

player/lua/console.lua

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,8 +1740,14 @@ end)
17401740

17411741
-- Add a line to the log buffer
17421742
mp.register_script_message("log", function (message)
1743-
local log_buffer = log_buffers[id]
17441743
message = utils.parse_json(message)
1744+
if not message.log_id then return end
1745+
1746+
if not log_buffers[message.log_id] then
1747+
log_buffers[message.log_id] = {}
1748+
end
1749+
1750+
local log_buffer = log_buffers[message.log_id]
17451751

17461752
log_buffer[#log_buffer + 1] = {
17471753
text = message.text,
@@ -1754,7 +1760,7 @@ mp.register_script_message("log", function (message)
17541760
table.remove(log_buffer, 1)
17551761
end
17561762

1757-
if not open then
1763+
if not open or message.log_id ~= id then
17581764
return
17591765
end
17601766

@@ -1770,9 +1776,10 @@ mp.register_script_message("log", function (message)
17701776
end
17711777
end)
17721778

1773-
mp.register_script_message("set-log", function (log)
1779+
mp.register_script_message("set-log", function (log, log_id)
1780+
if not log_id then return end
17741781
log = utils.parse_json(log)
1775-
log_buffers[id] = {}
1782+
log_buffers[log_id] = {}
17761783

17771784
for i = 1, #log do
17781785
if type(log[i]) == "table" then
@@ -1789,7 +1796,9 @@ mp.register_script_message("set-log", function (log)
17891796
end
17901797
end
17911798

1792-
render()
1799+
if log_id == id then
1800+
render()
1801+
end
17931802
end)
17941803

17951804
mp.register_script_message("complete", function (message)

player/lua/input.lua

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ local utils = require "mp.utils"
1919
local input = {}
2020
local handle_counter = 1
2121
local latest_handler_id
22+
local latest_log_id
2223

2324
local function get_non_callbacks(t)
2425
local non_callbacks = {}
@@ -66,14 +67,20 @@ local function register_event_handler(t)
6667
return handler_id
6768
end
6869

69-
function input.get(t)
70+
local function input_request(t)
7071
t.has_completions = t.complete ~= nil
7172

7273
mp.commandv("script-message-to", "console", "get-input", mp.get_script_name(),
7374
register_event_handler(t), utils.format_json(get_non_callbacks(t)))
7475
end
7576

76-
input.select = input.get
77+
function input.get(t)
78+
-- input.select does not support log buffers, so cannot override the latest id.
79+
latest_log_id = t.id or mp.get_script_name()..(t.prompt or "")
80+
return input_request(t)
81+
end
82+
83+
input.select = input_request
7784

7885
function input.terminate()
7986
mp.commandv("script-message-to", "console", "disable", utils.format_json({
@@ -83,19 +90,25 @@ end
8390

8491
function input.log(message, style, terminal_style)
8592
mp.commandv("script-message-to", "console", "log", utils.format_json({
93+
log_id = latest_log_id,
8694
text = message,
8795
style = style,
8896
terminal_style = terminal_style,
8997
}))
9098
end
9199

92100
function input.log_error(message)
93-
mp.commandv("script-message-to", "console", "log",
94-
utils.format_json({ text = message, error = true }))
101+
mp.commandv("script-message-to", "console", "log", utils.format_json({
102+
log_id = latest_log_id,
103+
text = message,
104+
error = true
105+
}))
95106
end
96107

97108
function input.set_log(log)
98-
mp.commandv("script-message-to", "console", "set-log", utils.format_json(log))
109+
if latest_log_id then return end
110+
mp.commandv("script-message-to", "console", "set-log",
111+
utils.format_json(log), latest_log_id)
99112
end
100113

101114
return input

0 commit comments

Comments
 (0)