c:在子进程中运行的 exec() 中捕获段错误
编辑:
我正在尝试编写一个简单的冒烟测试,其中测试所有选项和合理参数。
我使用 popen() 来执行应该测试的程序。 使用这种方法不起作用,因为如果进程因信号(SIGINT、SIGSEGV...)而终止,来自 popen() 的管道不会告诉我发生了什么。
编写信号处理程序没有帮助,因为 popen 创建了一个接收信号的新进程,但不是我的烟雾测试。
感谢这些答案,我使用了 pipeline()、fork() 和 execv() 来创建我自己的 popen() 版本。
当程序现在出现段错误时,存在管道无用的问题(读取导致奇怪的行为 - >阻止进程,直到我向父级发送 sigkill!)
为了避免这种情况,我尝试了不同的方法,我的解决方案如下(这很简单,但我花了一段时间才弄清楚)。所以这是我的示例代码:
static int child_dead = 0;
void sigaction_sigchld(int signal) { /* Child died */
child_dead = 1;
}
int main(int argc, char *argv[], char *env[])
{
char *crashing_program = "/program_path/and_name";
int ret;
int byte;
pid = fork();
if(pid == 0) /* Child */
{
execve(crashing_program, argv, env);
/* if execve returns that it mus have failed! */
fprintf(stderr, "Exec failed\n");
_exit(-1);
} else /* Parent */
{
if(!child_dead)
{
byte = read(pipe_out[1], line, BUFFSIZE);
if(!byte){
perror("Smoketest:Line:xxx");
} else
{
fprintf(stdout, line);
}
}
wait(&child_status);
/*
check if the child died with SIGSEGV etc
*/
}
只要我一次只有一个孩子,这似乎就可以正常工作,但这对我来说已经足够了。如果有人对我有更好的想法或任何提示,我很乐意更新此条目。
最后但并非最不重要的一点:当然,使用这种方法可能无法进行任何清理。
干杯。
EDIT:
I am trying to write a simple smoketest, where all options and reasonable parameters are tested.
I used popen() to execute the program that should be tested.
Using this approach does not work, because if the process dies with a signal (SIGINT, SIGSEGV...) the pipe from popen() does not tell me what happend.
Writing a signal handler did not help since popen creates a new process that receives the signals but not my smoketest.
Thanks to the answers i used pipe(), fork() and execv() to create my own popen()-version.
When the program now segfaults there is the problem that the pipe is useless (a read caused weird behavior -> blocked the process until i send a sigkill to the parent!)
To avoid this i tried different things and my solution is the following (it is simple but it took me a while to figure it out). so here is my example-code:
static int child_dead = 0;
void sigaction_sigchld(int signal) { /* Child died */
child_dead = 1;
}
int main(int argc, char *argv[], char *env[])
{
char *crashing_program = "/program_path/and_name";
int ret;
int byte;
pid = fork();
if(pid == 0) /* Child */
{
execve(crashing_program, argv, env);
/* if execve returns that it mus have failed! */
fprintf(stderr, "Exec failed\n");
_exit(-1);
} else /* Parent */
{
if(!child_dead)
{
byte = read(pipe_out[1], line, BUFFSIZE);
if(!byte){
perror("Smoketest:Line:xxx");
} else
{
fprintf(stdout, line);
}
}
wait(&child_status);
/*
check if the child died with SIGSEGV etc
*/
}
This seems to work fine as long as i only have one child at a time which is sufficient for me though. I anyone has a better idea or any tipps for me i would be glad to update this entry.
Last but not least: Of course using this method it is probably impossible to do any cleanup.
Cheers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请参阅
waitpid(2)
的文档。您可以使用许多宏来测试子进程是如何终止的。特别是,您可以使用WIFSIGNALED()
和WTERMSIG()
来测试子进程是否被信号终止,如果是,是哪个信号:编辑:如上所述在注释中,您宁愿使用 fork 和 exec,然后使用
waitpid(2)
来正确更新状态。See the documentation for
waitpid(2)
. There are a bunch of macros you can use to test how the child process was terminated. In particular, you can useWIFSIGNALED()
andWTERMSIG()
to test if the child process was terminated by a signal, and if so, which signal:Edit: As stated in the comments, you'd rather make use of fork and exec, then use
waitpid(2)
to correctly update status.