diff --git a/lib/awful/spawn.lua b/lib/awful/spawn.lua index b25ca803d..12fa498d8 100644 --- a/lib/awful/spawn.lua +++ b/lib/awful/spawn.lua @@ -29,6 +29,45 @@ local protected_call = require("gears.protected_call") local spawn = {} +local end_of_file +do + -- API changes, bug fixes and lots of fun. Figure out how a EOF is signalled. + local input + if not pcall(function() + -- No idea when this API changed, but some versions expect a string, + -- others a table with some special(?) entries + input = Gio.DataInputStream.new(Gio.MemoryInputStream.new_from_data("")) + end) then + input = Gio.DataInputStream.new(Gio.MemoryInputStream.new_from_data({})) + end + local line, length = input:read_line() + if not line then + -- Fixed in 2016: NULL on the C side is transformed to nil in Lua + end_of_file = function(arg) + return not arg + end + elseif tostring(line) == "" and #line ~= length then + -- "Historic" behaviour for end-of-file: + -- - NULL is turned into an empty string + -- - The length variable is not initialized + -- It's highly unlikely that the uninitialized variable has value zero. + -- Use this hack to detect EOF. + end_of_file = function(arg1, arg2) + return #arg1 ~= arg2 + end + else + assert(tostring(line) == "", "Cannot determine how to detect EOF") + -- The above uninitialized variable was fixed and thus length is + -- always 0 when line is NULL in C. We cannot tell apart an empty line and + -- EOF in this case. + require("gears.debug").print_warning("Cannot reliably detect EOF on an " + .. "GIOInputStream with this LGI version") + end_of_file = function(arg) + return tostring(arg) == "" + end + end +end + spawn.snid_buffer = {} function spawn.on_snid_callback(c) @@ -219,7 +258,7 @@ function spawn.read_lines(input_stream, line_callback, done_callback, close) -- Error print("Error in awful.spawn.read_lines:", tostring(length)) done() - elseif #line ~= length then + elseif end_of_file(line, length) then -- End of file done() else