Skip to content

Commit

Permalink
Send bactrace to stderr and capture it in test runner
Browse files Browse the repository at this point in the history
Servo's panic hook writes backtraces to stdout. This
patch changes it so they are written to stderr.

The crash test executor for servo in WPT grouping formatter
was also not capturing the output correctly for crashtests
as the log events were being aggregated based on thread name
which doesn't seem to match correctly in case of crashtests.
This patch also fixes the log grouping logic to be based on
test name.

Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
  • Loading branch information
mukilan and mrobinson committed Aug 17, 2023
1 parent 23bb5e1 commit 317b581
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 17 deletions.
16 changes: 10 additions & 6 deletions ports/winit/main2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,24 +117,28 @@ pub fn main() {
};
let current_thread = thread::current();
let name = current_thread.name().unwrap_or("<unnamed>");
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
let stderr = std::io::stderr();
let mut stderr = stderr.lock();
if let Some(location) = info.location() {
let _ = writeln!(
&mut stdout,
&mut stderr,
"{} (thread {}, at {}:{})",
msg,
name,
location.file(),
location.line()
);
} else {
let _ = writeln!(&mut stdout, "{} (thread {})", msg, name);
let _ = writeln!(&mut stderr, "{} (thread {})", msg, name);
}
if env::var("RUST_BACKTRACE").is_ok() {
let _ = backtrace::print(&mut stdout);
let _ = backtrace::print(&mut stderr);
}
drop(stderr);

if opts::get().hard_fail && !opts::get().multiprocess {
std::process::exit(1);
}
drop(stdout);

error!("{}", msg);
}));
Expand Down
6 changes: 2 additions & 4 deletions python/wpt/grouping_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,8 @@ def test_status(self, data: dict):
))

def process_output(self, data):
if data['thread'] not in self.running_tests:
return
test_name = self.running_tests[data['thread']]
self.test_output[test_name] += data['data'] + "\n"
if 'test' in data:
self.test_output[data['test']] += data['data'] + "\n"

def log(self, _):
pass
Expand Down
2 changes: 1 addition & 1 deletion tests/wpt/meta/MANIFEST.json
Original file line number Diff line number Diff line change
Expand Up @@ -465041,7 +465041,7 @@
[]
],
"executorservo.py": [
"a8ec38699616c5baf7a3b43b8149b89746308f35",
"0d22471e90e83fbfd80010001e8c60f509af8902",
[]
],
"executorservodriver.py": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def teardown(self):
ProcessTestExecutor.teardown(self)

def do_test(self, test):
self.test = test
self.result_data = None
self.result_flag = threading.Event()

Expand Down Expand Up @@ -156,7 +157,7 @@ def on_output(self, line):
else:
self.logger.process_output(self.proc.pid,
line,
" ".join(self.command))
" ".join(self.command), self.test.url)

def on_finish(self):
self.result_flag.set()
Expand Down Expand Up @@ -270,18 +271,19 @@ def screenshot(self, test, viewport_size, dpi, page_ranges):
return True, [base64.b64encode(data).decode()]

def do_test(self, test):
self.test = test
result = self.implementation.run_test(test)

return self.convert_result(test, result)

def on_output(self, line):
def on_output(line):
line = line.decode("utf8", "replace")
if self.interactive:
print(line)
else:
self.logger.process_output(self.proc.pid,
line,
" ".join(self.command))
" ".join(self.command), self.test.url)


class ServoTimedRunner(TimedRunner):
Expand Down Expand Up @@ -342,7 +344,7 @@ def do_crashtest(self, protocol, url, timeout):
env["HOST_FILE"] = self.hosts_path
env["RUST_BACKTRACE"] = "1"

command = build_servo_command(self.test,
self.command = build_servo_command(self.test,
self.test_url,
self.browser,
self.binary,
Expand All @@ -351,16 +353,23 @@ def do_crashtest(self, protocol, url, timeout):
extra_args=["-x"])

if not self.interactive:
self.proc = ProcessHandler(command,
self.proc = ProcessHandler(self.command,
env=env,
processOutputLine=[self.on_output],
storeOutput=False)
self.proc.run()
else:
self.proc = subprocess.Popen(command, env=env)
self.proc = subprocess.Popen(self.command, env=env)

self.proc.wait()

if self.proc.poll() >= 0:
return {"status": "PASS", "message": None}

return {"status": "CRASH", "message": None}

def on_output(self, line):
line = line.decode("utf8", "replace")
self.logger.process_output(self.proc.pid,
line,
" ".join(self.command), self.test.url)

0 comments on commit 317b581

Please sign in to comment.