隔离容易崩溃的 (SEGV) 但将关键的遗留代码加速到单独的二进制文件中

Isolate crash prone (SEGV) but speed critical legacy code into a separate binary

我有一个经过良好测试且没有崩溃的代码库(主要是 C++)。大多。代码的一部分——不可替代、难以维护或改进并链接到一个二进制库*——导致所有崩溃。这些不会经常发生,但一旦发生,整个程序就会崩溃。

          +----------------------+
          | Shiny new sane       |
          |  code base           |
          |                      |
          |  +-----------------+ |   If the legacy code crashes,
          |  |                 | |   the entire program does, too.
          |  |   Legacy Code   | |
          |  | * Crash prone * | |
          |  | int abc(data)   | |
          |  +-----------------+ |
          |                      |
          +----------------------+

是否可以将那部分代码提取到单独的程序中,从主程序启动,在这些程序之间移动数据(在 Linux、OS X 上,如果可能,Windows),容忍子进程崩溃并重新启动子进程?像这样:

        +----------------+         // start,
        | Shiny new sane | ------. // re-start on crash
        |  code base     |       | //   and
        |                |       v // input data
        |                |    +-----------------+
        |   return       |    |                 |
        |   results <-------- |   Legacy Code   |
        +----------------+    | * Crash prone * |
                              |  int abc(data)  |
       (or not results        +-----------------+
        because abc crashed)

理想情况下,通信速度足够快,以便可以用包装器透明地替换对 int abc(char *data) 的同步调用(假设非崩溃情况)。并且由于轻微的内存泄漏,遗留程序应该每隔一小时左右重新启动一次。崩溃是确定性的,因此错误的输入数据不应发送两次。

代码库是 C++11 和 C,著名的外部库是 Qt 和 boost。它在 Linux、OSX 和 Windows.

上运行

--
*: 一些 crashes/leaks 来自这个没有可用源代码的库。

嗯,如果我是你,我不会从这里开始......

然而,你就是你所在的地方。是的,你可以做到。您将必须序列化您的输入参数,发送它们,在子进程中反序列化它们,运行 函数,序列化输出,return 它们,然后反序列化它们。 Boost 将有很多有用的代码来帮助解决这个问题(参见 asio)。

全局变量会让生活更精彩"interesting"。遗留代码是否使用 Qt? - 这可能不喜欢被分成两个进程。

如果您只使用 Windows,我会说 "use DCOM" - 这让事情变得非常简单。

如果仅从一个线程使用旧版(处理 "return" 的代码只是查看是否需要重新启动,然后终止进程。),那么重新启动就足够简单了。如果您有多个线程,然后闪亮的代码将需要检查是否需要重新启动,阻止任何进一步的线程,等到所有调用都已 returned,重新启动进程,然后取消阻止所有内容。

Boost::interprocess 看起来拥有通信所需的一切 - 它具有共享内存、互斥锁和条件变量。 Boost::serialization 将完成编组和解组工作。