调用一个带有扭曲的库函数 - 修改它的一些行为

时间:2015-04-01 00:02:36

标签: c++ hook octave shared backtrace

我正在尝试将八度音程库嵌入到更大的程序中。我需要从这个更大的程序中随意启动和停止八度音译器。但是,唯一能够干净地停止八度音译器的函数也会调用exit(),这也会杀死更大的程序。八度音程库函数是clean_up_and_exit()。

理想情况下,我只想调用清理部分(do_octave_atexit),并跳过调用退出。

我尝试了以下内容:

1)调用do_octave_atexit,但符号不会在八度音阶库中导出。无论如何我试图访问它但无济于事。

2)我试图通过ld_preload挂钩调用exit,并用一个不退出的函数替换它。这一切搞砸了所有其他的退出调用也被搞砸了。

3)我试图通过调用回溯检测调用函数来检测何时仅通过八度音调调用exit以防止它被调用。由于某种原因,这并没有表明我期望成为真正的呼叫层次结构。由于某种原因,它只显示了main函数,并且没有通过octave库显示调用层次结构的内容。因此无法检测到来自八度的呼叫。

我用来调用八度音阶函数的代码如下:

//
// Octave Setup Functions
//
extern "C" void oct_init (const char * path) {
  string_vector argv (2);
  argv(0) = "embedded";
  argv(1) = "-q";

  octave_main (2, argv.c_str_vec (), 1);
  if(strlen(path) > 1) {
    oct_addpath(path);
  }
}

extern "C" void oct_exit (void) {
  printf("Exiting!");
  clean_up_and_exit (1,1);
}

这里的关键功能是clean_up_and_exit - 它在八度音源中实现为:

void clean_up_and_exit (int retval, bool safe_to_return)
{
  do_octave_atexit ();

  if (octave_link::exit (retval))
  {
    if (safe_to_return)
      return;
    else
     {
       gnulib::sleep (86400);
     }
 }
 else
 {
   if (octave_exit)
     (*octave_exit) (retval);
 }
}

所以上面的代码调用了我想要的函数(do_octave_atexit),然后继续调用* octave_exit - 这是一个指向exit()的函数指针。

理想情况下,我想要a)阻止此调用exit(),或b)仅在来自八度音阶时捕获调用并阻止它,并在来自其他来源时允许它。到目前为止,我还没能做到a)或b)!

所以在这一点上我没有想法。我可以重新编译八度音程,但是这个解决方案应该适用于八度音调安装。

这只需要在linux / gcc环境下工作。

对这个非常棘手的问题的任何和所有建议都非常感激。

1 个答案:

答案 0 :(得分:1)

您必须分叉,并在单独的进程上运行Octave。这是一个关于如何做的简单示例:

#include <unistd.h>
#include <iostream>

#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h>

int
main_octave (void)
{
  string_vector argv (2);
  argv(0) = "embedded";
  argv(1) = "-q";

  octave_main (2, argv.c_str_vec (), 1);

  octave_value_list out = feval ("pi", octave_value_list (0), 1);
  if (! error_state && out.length () > 0)
    std::cout << "pi is " << out(0).double_value () << std::endl;
  else
    std::cout << "invalid\n";

  clean_up_and_exit (0);
}

int
main (void)
{
  pid_t pid = fork();
  if (pid == 0)
    main_octave ();
  else if (pid > 0)
    {
      std::cout << "Parent process going for a nap" << std::endl;
      sleep (5);
    }
  else
    {
      std::cout << "Unable to fork()" << std::endl;
      return 1;
    }
  std::cout << "Leaving standalone application" << std::endl;
  return 0;
}

在我的系统上返回:

$ mkoctfile --link-stand-alone embedded.cc -o embedded
$ ./embedded
Parent process going for a nap
pi is 3.14159
Leaving standalone application

因此,您可以在退出Octave流程后继续运行您的应用程序。当然,如果你想多次启动和停止Octave,那么你将不得不多次分叉。另外,我建议你在Octave帮助邮件列表上询问这些事情,你更有可能在那里更快地得到有用的答案。