在析构函数中的main之后无法读取exit_code

时间:2018-02-15 10:22:03

标签: c linux

我正在使用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);
}

1 个答案:

答案 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杀死。