rust - 有没有办法在 fsanitize 中断/崩溃时捕获子进程标准输出?
问题描述
我们有一个程序来测试其他程序。它只是比较某些输入上的输出是否正确。出于几个原因,我想从 Valgrind 切换到 fsanitize。
问题是我们的 Rust 程序无法使用 fsanitize 捕获具有某些错误的子进程的标准输出,但是使用 valgrind 时可以捕获所有输出。
那将是子进程。
let mut run_cmd = Command::new(format!("./{}", &self.meta.projdata.project_name))
//assuming makefile_path = project path
.current_dir(
&self
.meta
.projdata
.makefile_path
.as_ref()
.unwrap_or(&String::from("./")),
)
.args([&self.argv].iter().filter(|s| !s.is_empty()))
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.envs(envs)
.spawn()
.expect("could not spawn process");
如果它在一定时间后仍然运行,它将被杀死。
fn command_timeout(
cmd: Child,
timeout: i32,
number: i32,
) -> Result<(String, i32), ExecuteError> {
let mut cmd = cmd;
let mut output = String::new();
match cmd
.wait_timeout(Duration::from_secs(timeout as u64))
.unwrap()
{
Some(expr) => {
let mut tmp: Vec<u8> = Vec::new();
cmd.stdout
.as_mut()
.unwrap()
.read_to_end(&mut tmp)
.expect("could not read stdout");
output = format!("{}{}", output, String::from_utf8_lossy(&tmp));
let retvar = expr.code().unwrap_or(-1);
return Ok((output, retvar));
}
None => {
println!("killing {} beacause of timeout", number);
cmd.kill().expect("Upps, can't kill this one");
return Err(ExecuteError::Timeout);
}
}
}
这个有问题的测试用例的输出是:
./a2
output1 from c
AddressSanitizer:DEADLYSIGNAL
=================================================================
==11907==ERROR: AddressSanitizer: stack-overflow on address 0x7ffef3111660 (pc 0x565288af853a bp 0x7ffef310c8f0 sp 0x7ffef310c820 T0)
#0 0x565288af853a in main (/home/k/esp/students/assignment2espep_693/a2+0xfc53a)
#1 0x7fd97bd0c151 in __libc_start_main (/usr/lib/libc.so.6+0x28151)
#2 0x565288a1c1cd in _start (/home/k/esp/students/assignment2espep_693/a2+0x201cd)
SUMMARY: AddressSanitizer: stack-overflow (/home/k/esp/students/assignment2espep_693/a2+0xfc53a) in main
==11907==ABORTING
重现问题的示例 C 代码:
#include <stdio.h>
int main()
{
char array[1];
puts("output1 from c");
array[20000] = 'c';
printf("output2 from c: %llu\n", (long long unsigned) (array[20000]) ); //this is on purpose
return 0;
}
如果我现在通过 Rust 使用相同的输入文件,则 output / tmp 变量将为空。使用 fsanitize 时有什么方法可以捕获输出吗?我知道 fsanitize 打印到 stderr 并且这目前被忽略但我不明白为什么 stdout 上的子输出也没有被捕获。
C程序是用clang -Wall -Wextra -pedantic -std=c17 -fsanitize=address -fsanitize-recover=address
它开始于ASAN_OPTIONS=halt_on_error=0 ./testrunner
解决方案
推荐阅读
- angular - 如何为缺货天数实施自定义日期验证
- excel-formula - 使用 Excel 索引和匹配函数返回多个结果
- jax-rs - 没有 web.xml 的 JAX-RS 的 HTTP 基本身份验证
- javascript - 如何使用javascript在字符串中添加符号
- android - 如何根据内容更改 TextView 的位置
- elasticsearch - 从 ElasticSearch 批量索引获取详细响应
- vue.js - VueJs + BootstrapVue:使用数据分页编辑对象
- javascript - Angular 无法识别来自 css3 的图像的静态路径
- excel - 不确定如何排除故障
- javascript - 画布像素化 - 调整像素大小