Commit 8502ac4b authored by Karel Koci's avatar Karel Koci 🤘

subprocess: fix problem with lost stdout content

I originally was thinking that Lua is doing something nasty like
duplicating original file descriptor for stdout but it turns out that
exec was a culprit. For some reason a call to exec truncates (or at
least removes unfinished line) from stdout. I have no idea why it
behaves that way but adding flush just after callback (before exec)
solves that problem and allows us to correctly use print in callback.
The weird part is that the same thing does not happen with stderr but
non the less I also added flush for it.
parent a803ad41
......@@ -37,7 +37,7 @@ void subproc_kill_t(int timeout) {
}
static void run_child(const char *cmd, const char *args[], subproc_callback callback, void *data, int p_out[2], int p_err[2]) {
// Close unneded FDs
// Close unneded FDs and replace stdout and stderr
ASSERT(close(0) != -1);
ASSERT(close(p_out[0]) != -1);
ASSERT(dup2(p_out[1], 1) != -1 && close(p_out[1]) != -1);
......@@ -46,6 +46,9 @@ static void run_child(const char *cmd, const char *args[], subproc_callback call
// Callback
if (callback)
callback(data);
fflush(stdout);
fflush(stderr);
// Note: We have to flush standard output because for some reason it looses content on exec
// Exec
size_t arg_c = 2; // cmd and NULL terminator
for (const char **p = args; *p; p++)
......
......@@ -21,48 +21,55 @@ require 'lunit'
module("subproc", package.seeall, lunit.testcase)
--[[
On Debian lunit for some reason prints when invoked in subprocess information
about executed test suite again. This of course taints start of subprocess.
This function removes known problematic two first lines from beginning of output
if pattern is detected.
]]
local function fix_out(out)
if out:find('Loaded testsuite with', 1, true) ~= nil then
local _, last = out:find('\n\n', 1, true)
return out:sub(last + 1)
end
return out
end
function test_exit_code()
local ok, out = subprocess(LST_HOOK, "Test: true", 1000, "true")
assert_equal(0, ok)
assert_equal("", out)
assert_equal("", fix_out(out))
local ok, out = subprocess(LST_HOOK, "Test: false", 1000, "false")
assert_not_equal(0, ok)
assert_equal("", out)
assert_equal("", fix_out(out))
end
function test_output()
local ok, out = subprocess(LST_HOOK, "Test: echo", 1000, "echo", "hello")
assert_equal(0, ok)
assert_equal("hello\n", out)
assert_equal("hello\n", fix_out(out))
local ok, out = subprocess(LST_HOOK, "Test: echo stderr", 1000, "sh", "-c", "echo hello >&2")
assert_equal(0, ok)
assert_equal("hello\n", out)
assert_equal("hello\n", fix_out(out))
end
function test_timeout()
subprocess_kill_timeout(0)
local ok, out = subprocess(LST_HOOK, "Test: sleep", 1000, "sleep", "2")
assert_not_equal(0, ok)
assert_equal("", out)
assert_equal("", fix_out(out))
end
function test_callback()
subprocess_kill_timeout(0)
local ok, out = subprocess(LST_HOOK, "Test: env", 1000, function () io.stderr:write("Hello callback\n") end, "true")
local ok, out = subprocess(LST_HOOK, "Test: env", 1000, function () io.stderr:write("Hello callback") end, "true")
assert_equal(0, ok)
assert_equal("Hello callback\n", out)
--[[
We are testing here with stderr for a reason. There seems to be some problem
with lua's stdout and dup. No lua stdout works after dup2 on f.d. 1 on some
testing platforms. We are not planning to print messages from lua from
subprocess on daily base so let's not care.
]]
local ok, out = subprocess(LST_HOOK, "Test: env", 1000, function () setenv("TESTENV", "Hello env") end, "sh", "-c", "echo $TESTENV")
assert_equal("Hello callback", fix_out(out))
local ok, out = subprocess(LST_HOOK, "Test: env", 1000, function () setenv("TESTENV", "Hello env callback") end, "sh", "-c", "echo $TESTENV")
assert_equal(0, ok)
assert_equal("Hello env\n", out)
assert_equal("Hello env callback\n", fix_out(out))
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment