autoupdater: add timeouts to wget calls

The -T parameter only seems to limit the maximum time between received
packets, but not the overall run time.

This adds simple timeouts to the wget calls (5 minutes for the manifest,
30 minutes for the image). The implementation is very simple, only checking
the manifest timeout each time a line was received, and the image timeout
once a second. A more elegent fix seems like overkill, as the Lua
autoupdater will be replaced with a new implementation after Gluon 2016.2
anyways.
This commit is contained in:
Matthias Schiffer 2016-09-08 03:09:30 +02:00
parent 1acb4b1d3a
commit 90380414f1
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
2 changed files with 35 additions and 7 deletions

View File

@ -7,14 +7,29 @@ module('autoupdater.util', package.seeall)
-- Executes a command in the background, without parsing the command through a shell (in contrast to os.execute) -- Executes a command in the background, without parsing the command through a shell (in contrast to os.execute)
function exec(...) function exec(timeout, ...)
local pid, errno, error = nixio.fork() local pid, errno, error = nixio.fork()
if pid == 0 then if pid == 0 then
nixio.execp(...) nixio.execp(...)
os.exit(127) os.exit(127)
elseif pid > 0 then elseif pid > 0 then
local wpid, status, code = nixio.waitpid(pid) if timeout then
return wpid and status == 'exited' and code local starttime = os.time()
while true do
if os.difftime(os.time(), starttime) > timeout then
nixio.kill(pid, nixio.const.SIGTERM)
end
local wpid, status, code = nixio.waitpid(pid, 'nohang')
if wpid then
return wpid and status == 'exited' and code
end
nixio.nanosleep(1)
end
else
local wpid, status, code = nixio.waitpid(pid)
return wpid and status == 'exited' and code
end
else else
return pid, errno, error return pid, errno, error
end end
@ -69,7 +84,7 @@ function run_dir(dir)
for _, entry in ipairs(files) do for _, entry in ipairs(files) do
if is_ok(entry) then if is_ok(entry) then
exec(dir .. '/' .. entry) exec(nil, dir .. '/' .. entry)
end end
end end
end end

View File

@ -129,9 +129,21 @@ local function read_manifest(mirror)
-- Remove potential trailing slash -- Remove potential trailing slash
mirror = mirror:gsub('/$', '') mirror = mirror:gsub('/$', '')
local starttime = os.time()
local manifest_loader = io.popen(string.format("exec wget -T 120 -O- '%s/%s.manifest'", mirror, branch.name), 'r')
-- Read all lines from the manifest -- Read all lines from the manifest
-- The upper part is saves to lines, the lower part to sigs -- The upper part is saved to lines, the lower part to sigs
for line in io.popen(string.format("exec wget -T 120 -O- '%s/%s.manifest'", mirror, branch.name), 'r'):lines() do for line in manifest_loader:lines() do
-- If the manifest download takes more than 5 minutes, we don't really
-- have a chance to download a whole image
if os.difftime(os.time(), starttime) > 300 then
io.stderr:write("Timeout while reading manifest.\n")
manifest_loader:close()
return nil
end
if not sep then if not sep then
if line == '---' then if line == '---' then
sep = true sep = true
@ -194,7 +206,8 @@ end
-- Downloads the firmware image from a mirror to a given output file -- Downloads the firmware image from a mirror to a given output file
local function fetch_firmware(mirror, filename, output) local function fetch_firmware(mirror, filename, output)
if autoupdater_util.exec('wget', '-T', '120', '-O', output, mirror .. '/' .. filename) ~= 0 then -- Let's give the image download 30 minutes, hopefully more than enough
if autoupdater_util.exec(1800, 'wget', '-T', '120', '-O', output, mirror .. '/' .. filename) ~= 0 then
io.stderr:write('Error downloading the image from ' .. mirror .. '\n') io.stderr:write('Error downloading the image from ' .. mirror .. '\n')
return false return false
end end