Skip to content

Commit 60fa827

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 cf7eca1 commit 60fa827

4 files changed

Lines changed: 62 additions & 30 deletions

File tree

DOCS/man/lua.rst

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -980,16 +980,18 @@ REPL.
980980
requests made by other scripts.
981981

982982
``input.log(message, style, terminal_style)``
983-
Add a line to the log buffer. ``style`` can contain additional ASS tags to
984-
apply to ``message``, and ``terminal_style`` can contain escape sequences
985-
that are used when the console is displayed in the terminal.
983+
Add a line to the log buffer of the latest ``input.get()`` request.
984+
``style`` can contain additional ASS tags to apply to ``message``,
985+
and ``terminal_style`` can contain escape sequences that are used
986+
when the console is displayed in the terminal.
986987

987988
``input.log_error(message)``
988-
Helper to add a line to the log buffer with the same color as the one used
989+
Helper to add an error line to the log buffer of the latest ``input.get()``
990+
request. The line is styled with the same color as the one used
989991
for commands that error. Useful when the user submits invalid input.
990992

991993
``input.set_log(log)``
992-
Replace the entire log buffer.
994+
Replace the entire log buffer of the latest ``input.get()`` request.
993995

994996
``log`` is a table of strings, or tables with ``text``, ``style`` and
995997
``terminal_style`` keys.

player/javascript/defaults.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,8 @@ mp.options = { read_options: read_options };
654654
* input
655655
*********************************************************************/
656656
var input_handle_counter = 1;
657-
var latest_handler_id;
657+
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,13 +687,18 @@ function register_event_handler(t) {
686687
return handler_id;
687688
}
688689

690+
function input_request(t) {
691+
t.has_completions = t.complete !== undefined;
692+
t.script_name = mp.script_name;
693+
t.handler_id = register_event_handler(t);
694+
695+
mp.commandv("script-message-to", "console", "get-input", JSON.stringify(t));
696+
}
697+
689698
mp.input = {
690699
get: function(t) {
691-
t.has_completions = t.complete !== undefined;
692-
t.script_name = mp.script_name;
693-
t.handler_id = register_event_handler(t);
694-
695-
mp.commandv("script-message-to", "console", "get-input", JSON.stringify(t));
700+
latest_log_id = t.id || mp.script_name + (t.prompt || "");
701+
return input_request(t);
696702
},
697703
terminate: function () {
698704
mp.commandv("script-message-to", "console", "disable", JSON.stringify({
@@ -701,21 +707,26 @@ mp.input = {
701707
},
702708
log: function (message, style, terminal_style) {
703709
mp.commandv("script-message-to", "console", "log", JSON.stringify({
710+
log_id: latest_log_id,
704711
text: message,
705712
style: style,
706713
terminal_style: terminal_style,
707714
}));
708715
},
709716
log_error: function (message) {
710-
mp.commandv("script-message-to", "console", "log",
711-
JSON.stringify({ text: message, error: true }));
717+
mp.commandv("script-message-to", "console", "log", JSON.stringify({
718+
log_id: latest_log_id,
719+
text: message,
720+
error: true,
721+
}));
712722
},
713723
set_log: function (log) {
724+
if (!latest_log_id) return;
714725
mp.commandv("script-message-to", "console", "set-log",
715-
JSON.stringify(log));
726+
JSON.stringify(log), latest_log_id);
716727
}
717728
}
718-
mp.input.select = mp.input.get
729+
mp.input.select = input_request;
719730

720731
/**********************************************************************
721732
* various

player/lua/console.lua

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,8 +1740,11 @@ 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]
1744-
message = utils.parse_json(message)
1743+
message = utils.parse_json(message or '')
1744+
if not message or not message.log_id then return end
1745+
1746+
local log_buffer = log_buffers[message.log_id]
1747+
if not log_buffer then return end
17451748

17461749
log_buffer[#log_buffer + 1] = {
17471750
text = message.text,
@@ -1754,7 +1757,7 @@ mp.register_script_message("log", function (message)
17541757
table.remove(log_buffer, 1)
17551758
end
17561759

1757-
if not open then
1760+
if not open or message.log_id ~= id then
17581761
return
17591762
end
17601763

@@ -1770,9 +1773,10 @@ mp.register_script_message("log", function (message)
17701773
end
17711774
end)
17721775

1773-
mp.register_script_message("set-log", function (log)
1776+
mp.register_script_message("set-log", function (log, log_id)
1777+
if not log or not log_id then return end
17741778
log = utils.parse_json(log)
1775-
log_buffers[id] = {}
1779+
log_buffers[log_id] = {}
17761780

17771781
for i = 1, #log do
17781782
if type(log[i]) == "table" then
@@ -1789,7 +1793,9 @@ mp.register_script_message("set-log", function (log)
17891793
end
17901794
end
17911795

1792-
render()
1796+
if log_id == id then
1797+
render()
1798+
end
17931799
end)
17941800

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

player/lua/input.lua

Lines changed: 22 additions & 9 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,15 +67,21 @@ 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
t.script_name = mp.get_script_name()
7273
t.handler_id = register_event_handler(t)
7374

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

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

7986
function input.terminate()
8087
mp.commandv("script-message-to", "console", "disable", utils.format_json({
@@ -84,19 +91,25 @@ end
8491

8592
function input.log(message, style, terminal_style)
8693
mp.commandv("script-message-to", "console", "log", utils.format_json({
87-
text = message,
88-
style = style,
89-
terminal_style = terminal_style,
90-
}))
94+
log_id = latest_log_id,
95+
text = message,
96+
style = style,
97+
terminal_style = terminal_style,
98+
}))
9199
end
92100

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

98109
function input.set_log(log)
99-
mp.commandv("script-message-to", "console", "set-log", utils.format_json(log))
110+
if not latest_log_id then return end
111+
mp.commandv("script-message-to", "console", "set-log",
112+
utils.format_json(log), latest_log_id)
100113
end
101114

102115
return input

0 commit comments

Comments
 (0)