隔离崩溃倾向 (SEGV),但将关键遗留代码加速到单独的二进制文件中
Posted
技术标签:
【中文标题】隔离崩溃倾向 (SEGV),但将关键遗留代码加速到单独的二进制文件中【英文标题】:Isolate crash prone (SEGV) but speed critical legacy code into a separate binary 【发布时间】:2016-03-28 15:11:34 【问题描述】:我有一个经过良好测试且无崩溃的代码库(主要是 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 上运行。
-- *:一些崩溃/泄漏源于该库,该库没有可用的源代码。
【问题讨论】:
我的建议是重写遗留代码 - 这将是一个比试图解决它崩溃的问题更好的解决方案。 很遗憾,重写是绝对不可能,它需要太多非常专业的知识,而编写它的人已经不在了。 你有密码。你可以看到它的作用。可能需要多少专业知识?它是否可提取取决于代码 - 如果您对它的理解不足以重写它,那么您对它的理解就不足以确定您对它所做的任何事情都是安全的。 您可以使用一些套接字,如果Shiny
无法连接,他会启动旧版。旧版收听、等待数据并使用int
回答。客户端等待应答,万一连接丢失,数据触发bug,请勿重试。
Catch Segfault or any other errors/exceptions/signals in C++ like catching exceptions in Java的可能重复
【参考方案1】:
好吧,如果我是你,我不会从这里开始......
然而,你在哪里。是的,你可以做到。你将不得不序列化你的输入参数,发送它们,在子进程中反序列化它们,运行函数,序列化输出,返回它们,然后反序列化它们。 Boost 将有很多有用的代码来帮助解决这个问题(参见 asio)。
全局变量将使生活更加“有趣”。遗留代码是否使用 Qt? - 那可能不喜欢被分成两个进程。
如果您只使用 Windows,我会说“使用 DCOM”——它使这变得非常简单。
如果仅从一个线程使用遗留系统,则重新启动非常简单(处理“返回”的代码只是查看它是否需要重新启动,并终止进程。)如果您有多个线程,那么闪亮的代码将需要检查是否需要重新启动,阻塞任何其他线程,等待所有调用返回,重新启动进程,然后解除阻塞。
Boost::interprocess 看起来拥有通信所需的一切——它有共享内存、互斥体和条件变量。 Boost::serialization 将完成编组和解组的工作。
【讨论】:
在遗留方面没有全局变量或 Qt,只有一两个纯函数感兴趣。 tcp/udp 套接字是唯一的可移植方式吗?共享内存和信号会想到其他低级工具。 sockets 无疑是最便携的方式。 Boost 有一个共享内存库,所以它应该可以工作。不了解信号,它们在 posix/Windows 世界中非常不同。如果您的参数/结果包含指针或具有虚函数,您仍然需要序列化/反序列化(无论如何这可能是个好主意 - 否则版本偏差会导致噩梦般的问题)。以上是关于隔离崩溃倾向 (SEGV),但将关键遗留代码加速到单独的二进制文件中的主要内容,如果未能解决你的问题,请参考以下文章
MobileAds.initialize(this) 崩溃 致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR)
SIGSEGV SEGV_ACCERR 崩溃报告 - 怎么办?
sigsegv segv_accerr 在 ios7 中崩溃 mkmapview
当自动释放池耗尽时,NSFileAttributes dealloc 中的 SIGSEGV SEGV_ACCERR 崩溃?
信号11(SIGSEGV),代码1(SEGV_MAPERR),故障地址0x7f4485ff1820
java.lang.Error:信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR) Android 应用