gcc/Linux:hook exit()调用以防止发生退出

gcc/Linux:hook exit()调用以防止发生退出,c,linux,gcc,hook,exit,C,Linux,Gcc,Hook,Exit,我有一个非常独特的例子,我从更高级别的C程序调用第三方库(我无法修改) 这段代码有一个调用exit()的清理例程,该例程终止整个应用程序 但是,我现在不想终止整个应用程序,因为主应用程序还必须完成一些工作 因此,为了解决这个问题,我尝试“欺骗”这个第三方库,使用dlsym临时“别名”exit()函数调用一个伪函数,然后将exit()恢复到其正常状态。 这个解决方案几乎可以工作-使用LD_PRELOAD指向虚拟出口包装器,我可以看到这个虚拟出口函数正在被调用-但是,在这之后,当这个函数超出范围时,

我有一个非常独特的例子,我从更高级别的C程序调用第三方库(我无法修改)

这段代码有一个调用exit()的清理例程,该例程终止整个应用程序

但是,我现在不想终止整个应用程序,因为主应用程序还必须完成一些工作

因此,为了解决这个问题,我尝试“欺骗”这个第三方库,使用dlsym临时“别名”exit()函数调用一个伪函数,然后将exit()恢复到其正常状态。 这个解决方案几乎可以工作-使用LD_PRELOAD指向虚拟出口包装器,我可以看到这个虚拟出口函数正在被调用-但是,在这之后,当这个函数超出范围时,我很快就会遇到一个分段错误

我怀疑这与gcc在默认情况下将名为noreturn的属性放在这个函数上有关

有没有办法删除此noreturn属性,或者更好的办法防止此第三方库调用exit()


任何建议都将不胜感激。

忽略以下事实:这可能是个坏主意,这是一个老问题,需要在评论中回答。 如果在Linux上使用gcc(可能是其他系统,我不知道),有一个替代解决方案

/*使用“gcc-Wl,-wrap,exit-o test wrap\u exit.c”编译*/
/*用“echo$?”检查退出状态*/
#包括
#包括
无效(实际)退出(int状态);;
无效(换行)退出(内部状态)
{
int stat=2;
printf(“试图以状态%d\n”退出,状态);
printf(“现在正在退出状态为%d\n的real”,stat);
__真实出口(stat);
}
内部主(空)
{
出口(1);
返回0;
}

如果这是线程化的:让
exit()
替换调用
pause()
完成后,向它发送一个信号,让
pause()
返回并调用真正的
exit()
?“因为仍然有一些工作必须由主应用程序完成。”可能
atexit()
会帮助你吗?即使你可以,试图欺骗那些认为自己在调用
exit()
的代码来调用其他东西,这是一个非常糟糕的想法。如果需要执行自己的清理,请在调用库例程之前执行清理,或者按照@alk建议注册退出处理程序。如果你根本不想退出,那就不要在那个时候调用那个库函数。。。粗鲁的。。。库函数首先调用
exit()
,至少在没有其他方法可以避免退出的情况下。特别是,如果图书馆坚持使用它的程序退出这种方式——考虑没有一个程序可以使用两个这样的库。如果是我,我会考虑把图书馆全部扔掉。@alk非常感谢-atexit似乎在耍花招。我将以前调用cleanup函数的例程更改为现在使用atexit注册对cleanup函数的调用。因此,现在只有当主应用程序退出时,才会调用讨厌的清理函数。
/* compile with "gcc -Wl,-wrap,exit -o test wrap_exit.c" */
/* check exit status with "echo $?" */

#include <stdio.h>
#include <stdlib.h>

void __real_exit(int status);

void __wrap_exit(int status)
{
  int stat = 2;
  printf("trying to exit with status %d\n", status);
  printf("now exiting for real with status %d\n", stat);
  __real_exit(stat);
}

int main(void)
{
  exit(1);

  return 0;
}