我正在使用LD_PRELOAD来包装可执行文件,并希望记录退出代码。在析构函数中,我正在读取包含退出代码的/ proc / self / stat文件,但它始终为零。这是我正在使用的代码,但没有预加载。
#include <stdio.h>
#include <stdlib.h>
int get_exit_code()
{
int exit_code = 0;
FILE *file = fopen("/proc/self/stat", "rt");
if (file) {
char *line = 0;
size_t line_len = 0;
if (getline(&line, &line_len, file) != -1) {
sscanf(line, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u "
"%*u %*u %*u %*u %*u %*d %*d %*d %*d %*d "
"%*d %*u %*u %*d %*u %*u %*u %*u %*u %*u "
"%*u %*u %*u %*u %*u %*u %*u %*d %*d %*u "
"%*u %*u %*u %*d %*u %*u %*u %*u %*u %*u "
"%*u %d",
&exit_code);
}
free(line);
fclose(file);
}
return exit_code;
}
int main(void)
{
return 37;
}
__attribute__ ((destructor)) void after_main(void)
{
int exit_code = get_exit_code(); // Always zero
printf("Exit code is %d\n", exit_code);
}
答案 0 :(得分:1)
析构函数作为进程退出的一部分运行 - 当您从main()
(或通过调用exit()
等)返回时,将调用析构函数。
因此,在您阅读/proc/self/stat
时,流程仍处于活动状态,/proc/self/stat
尚未更新。因为exit_code
中的/proc/self/stat
由于调用_exit
(或对内核进行的等效调用)系统调用而得到更新。但是直到所有的析构函数/退出处理程序都由C库运行才会发生这种情况;作为运行退出处理程序的一部分,它被作为最后一次调用。来自exit_code
的{{1}}实际上是针对内核提供给其父进程的/proc/self/stat
调用。这意味着无法从用户空间从进程本身获取wait(2)
的退出代码。
你可以做的是使用on_exit
(非标准的glibc函数)。这将为您提供正常程序终止时的返回代码。
您还需要插入/proc/self/stat
,以便在其他情况下,例如从信号处理程序调用{{1}}时,您有机会获得返回码。请注意,并非总是可以通过这种方式获取返回代码,例如,该进程会被_exit
或_exit
杀死。