- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个进程作为高可用性系统的一部分在 Linux 计算机上运行。该进程有一个主线程,它接收来自网络上其他计算机的请求并响应它们。还有一个心跳线程定期发送多播心跳数据包,让网络上的其他进程知道这个进程仍然存在并且可用——如果他们有一段时间没有收到来自它的任何心跳数据包,其中之一他们会假设这个进程已经死亡并接管它的职责,这样整个系统就可以继续工作。
这一切都运行良好,但前几天整个系统出现故障,当我调查原因时发现以下内容:
我的问题是,是否有一个优雅的解决方案可以处理此类故障? (显然,要做的一件事是修复 Linux 内核,这样它就不会“糟糕”,但考虑到 Linux 内核的复杂性,如果我的软件也能更优雅地处理 future 的其他内核错误,那就太好了。)
我不喜欢的一个解决方案是将心跳生成器放入主线程,而不是将其作为单独的线程运行,或者以其他方式将其绑定(bind)到主线程,这样如果主线程挂起无限期地向上,心跳将不会被发送。我不喜欢这个解决方案的原因是因为主线程不是实时线程,所以这样做会引入偶尔误报的可能性,即缓慢完成的操作被误认为是节点故障。如果可以的话,我想避免误报。
理想情况下,有一些方法可以确保失败的系统调用返回错误代码,或者如果这不可能,则让我的进程崩溃;其中任何一个都会停止心跳数据包的生成并允许进行故障转移。有什么办法可以做到这一点,或者不可靠的内核是否也会使我的用户进程也变得不可靠?
最佳答案
我的第二个建议是使用 ptrace 来查找当前指令指针。您可以有一个父线程跟踪您的进程并每秒中断它以检查当前的 RIP 值。这有点复杂,所以我写了一个演示程序:(仅限 x86_64,但应该可以通过更改寄存器名称来解决。)
#define _GNU_SOURCE
#include <unistd.h>
#include <sched.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <linux/ptrace.h>
#include <sys/user.h>
#include <time.h>
// this number is arbitrary - find a better one.
#define STACK_SIZE (1024 * 1024)
int main_thread(void *ptr) {
// "main" thread is now running under the monitor
printf("Hello from main!");
while (1) {
int c = getchar();
if (c == EOF) { break; }
nanosleep(&(struct timespec) {0, 200 * 1000 * 1000}, NULL);
putchar(c);
}
return 0;
}
int main(int argc, char *argv[]) {
void *vstack = malloc(STACK_SIZE);
pid_t v;
if (clone(main_thread, vstack + STACK_SIZE, CLONE_PARENT_SETTID | CLONE_FILES | CLONE_FS | CLONE_IO, NULL, &v) == -1) { // you'll want to check these flags
perror("failed to spawn child task");
return 3;
}
printf("Target: %d; %d\n", v, getpid());
long ptv = ptrace(PTRACE_SEIZE, v, NULL, NULL);
if (ptv == -1) {
perror("failed monitor sieze");
exit(1);
}
struct user_regs_struct regs;
fprintf(stderr, "beginning monitor...\n");
while (1) {
sleep(1);
long ptv = ptrace(PTRACE_INTERRUPT, v, NULL, NULL);
if (ptv == -1) {
perror("failed to interrupt main thread");
break;
}
int status;
if (waitpid(v, &status, __WCLONE) == -1) {
perror("target wait failed");
break;
}
if (!WIFSTOPPED(status)) { // this section is messy. do it better.
fputs("target wait went wrong", stderr);
break;
}
if ((status >> 8) != (SIGTRAP | PTRACE_EVENT_STOP << 8)) {
fputs("target wait went wrong (2)", stderr);
break;
}
ptv = ptrace(PTRACE_GETREGS, v, NULL, ®s);
if (ptv == -1) {
perror("failed to peek at registers of thread");
break;
}
fprintf(stderr, "%d -> RIP %x RSP %x\n", time(NULL), regs.rip, regs.rsp);
ptv = ptrace(PTRACE_CONT, v, NULL, NULL);
if (ptv == -1) {
perror("failed to resume main thread");
break;
}
}
return 2;
}
请注意,这不是生产质量代码。您需要做大量的修复工作。
据此,你应该能够判断出程序计数器是否在递增,并且可以将其与其他信息(例如/proc/PID/status
)结合起来查找它是否正忙于系统调用。您还可以扩展 ptrace 的使用以检查正在使用的系统调用,这样您就可以检查等待的系统调用是否合理。
这是一个 hacky 解决方案,但我认为您不会找到解决此问题的非 hacky 解决方案。尽管有 hackiness,但我不认为(这是未经测试的)它会特别慢;我的实现每秒暂停一次被监视的线程,持续很短的时间——我猜这将在 100 微秒的范围内。从理论上讲,这大约是 0.01% 的效率损失。
关于linux - 没有误报风险的高可用性计算 : How to deal with a non-returning system call,?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30061396/
import lombok.Data; @Data public class Filter { private Operator operator; private Object va
我刚刚在 SonarQube 中发现了一个误导性问题,我们的代码如下(JS) {…} function test(searchQuery, role) { console.log("inputs: "
我想我发现了误报: const items = document.querySelectorAll(selectors); for (const item of items) { if(item)
这是我第一次尝试编写实现简单形式的堆栈跟踪的自定义异常类。 这是.h: class error { public: error (); error (const
我正在尝试构建我的第一个 XML 模式 validator 作为我的代码库和许多项目中的可重用组件。我花了一整天的时间尝试遵循示例并对其进行编码,现在已经启动并运行了概念验证。 唯一的问题是,它给了我
我的数据库中有一个表,其中有一个名为“tags”的字段,例如iOS、Android、Java、JavaScript 等。我想选择此表中的所有项目,这些项目与某些标签相匹配,例如 id | name |
我刚刚开始在一个现有的中型项目中试验 .NET 4 中的 CodeContracts,令我惊讶的是静态检查器向我发出有关以下代码片段的编译时警告: public class Foo { priv
我不知道为什么,但我以前没有问题,现在突然之间,我很久以前写的这个非常古老、可怕的新手程序触发了 Malwarebytes... :( 这个问题不是重复的,因为有问题的程序是在 (ANSI) C 而不
在 Ubuntu 9.10 下启动了一个 Git 存储库。终于升级到10.04。当前的 Git 是 1.7.0.4。 现在,当我编辑升级前最后更改的文件(使用 gedit)然后提交时,提交中充满了误报
在设置 mod_security 后,我收到了很多误报 [??]。我只是在检测中运行它,所以还没有问题,但是一旦我需要它上线,这些过滤器就会开始阻止请求。 恐怕我不能 100% 理解这些过滤器的重要性
引用 Valgrind 教程: Optimized code can cause valgrind to wrongly report uninitialized value errors. The
Sonar 是否有可能在分支之间传输“误报”? 这是我们的工作流程:我们在分支 1 中进行开发,我们对此分支进行 Sonar 检查,当分支 1 发布时,我们将其合并到主干中,然后我们从主干创建分支 2
我的代码库中有一个静态函数的实现,并且在运行 clang-tidy 时在它上面,我注意到当我很确定代码正确时,静态分析器指向可能的内存泄漏。 (我已经用 sanitizer 验证过)。我认为这很可能是
Coverity 标记了一个我无法理解的问题。 我有一个初始化器: 1686 arrayOfNodeIds componentRefs = (arrayOfNodeIds) { 1687 .s
react.js 发生了一些奇怪的事情 Top-Level API . 这是我的mocha 测试的摘录: it.only('should identify a ReactElement', funct
大家好,我在使用 Apple 的可达性代码时遇到了一些问题。我发现,即使设备正确连接到互联网,最初可达性代码也会发出 1 个错误通知(Networkstatus = NotReachable),然后是
我一直在尝试运行 Insure++使用一些科学代码并报告许多错误,尽管公平地说它正式不支持 K&R C,而且我不知道大量 K&R 函数对其评估过程有何影响。它正在测试的 C 和 C++ 代码正在从 W
当我尝试调用 CFileFind.FindFile(_T("D://Folder//*.txt")) 时,当唯一的文件是“foobar.txta”时,该方法返回 true . 但是,我不希望文件 fo
在我之前的问题 ( "Pylint E0202 False Positive?" ) 之后,这里是另一个问题(我想很具体) 我们正在使用模块子流程来执行子流程。 创建示例代码会产生以下结果: "Exa
我有一个包含 2,865,044 个条目和 3 级 MultiIndex 的数据框 MultiIndex.levels.names = ['year', 'country', 'productcode
我是一名优秀的程序员,十分优秀!