`
weishiym
  • 浏览: 33400 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

阿里云环境部署Hyperledger Fabric之SIGSEGV问题分析和解决经验分享

 
阅读更多

最近收到Hyperledger社区的一些朋友反馈在阿里云环境上部署开源区块链项目Hyperledger Fabric的过程中遇到了和SIGSEV相关的fatal error,正好笔者此前也遇到并解决过类似的问题,因此这里分享一下当时问题的分析过程和解决的经验,希望能为大家带来一点启发和帮助。


问题描述

在部署Hyperledger Fabric过程中,peer、orderer服务启动失败,同时cli容器上执行cli-test.sh测试时也报错。错误类型均是signal SIGSEGV: segmentation violation。错误日志示例如下:

2017-11-01 02:44:04.247 UTC [peer] updateTrustedRoots -> DEBU 2a0 Updating trusted root authorities for channel mychannel
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x63 pc=0x7f9d15ded259]
runtime stack:
runtime.throw(0xdc37a7, 0x2a)
        /opt/go/src/runtime/panic.go:566 +0x95
runtime.sigpanic()
        /opt/go/src/runtime/sigpanic_unix.go:12 +0x2cc
goroutine 64 [syscall, locked to thread]:
runtime.cgocall(0xb08d50, 0xc4203bcdf8, 0xc400000000)
        /opt/go/src/runtime/cgocall.go:131 +0x110 fp=0xc4203bcdb0 sp=0xc4203bcd70
net._C2func_getaddrinfo(0x7f9d000008c0, 0x0, 0xc420323110, 0xc4201a01e8, 0x0, 0x0, 0x0)

分析过程

我们进行了深入分析和试验,在Hyperledger Fabric这个bug https://jira.hyperledger.org/browse/FAB-5822的启发下,采用了如下workaround可以解决这个问题:

  • 在docker compose yaml里对peer、orderer、cli的环境变量加入GODEBUG=netdns=go

这个设置的作用是不采用cgo resolver (从错误日志里可看到是cgo resolver抛出的错误)而采用pure go resolver。

进一步分析golang在什么情况下会在cgo resolver和pure go resolver之间切换:

Name Resolution
The method for resolving domain names, whether indirectly with functions like Dial or directly with functions like LookupHost and LookupAddr, varies by operating system.
On Unix systems, the resolver has two options for resolving names. It can use a pure Go resolver that sends DNS requests directly to the servers listed in /etc/resolv.conf, or it can use a cgo-based resolver that calls C library routines such as getaddrinfo and getnameinfo.
By default the pure Go resolver is used, because a blocked DNS request consumes only a goroutine, while a blocked C call consumes an operating system thread. When cgo is available, the cgo-based resolver is used instead under a variety of conditions: on systems that do not let programs make direct DNS requests (OS X), when the LOCALDOMAIN environment variable is present (even if empty), when the RES_OPTIONS or HOSTALIASES environment variable is non-empty, when the ASR_CONFIG environment variable is non-empty (OpenBSD only), when /etc/resolv.conf or /etc/nsswitch.conf specify the use of features that the Go resolver does not implement, and when the name being looked up ends in .local or is an mDNS name.
The resolver decision can be overridden by setting the netdns value of the GODEBUG environment variable (see package runtime) to go or cgo, as in:
export GODEBUG=netdns=go    # force pure Go resolver
export GODEBUG=netdns=cgo   # force cgo resolver*

根据这一线索,我们对比了此前部署成功环境和最近部署失败环境各自的底层配置文件,最终找到了不同之处:

  • 在老环境(区块链部署成功)上的容器里,查看

    # cat /etc/resolv.conf 
    nameserver 127.0.0.11
    options ndots:0
  • 在新环境(区块链部署失败)上的容器里,查看

    # cat /etc/resolv.conf 
    nameserver 127.0.0.11
    options timeout:2 attempts:3 rotate single-request-reopen ndots:0

这个差异导致了老的成功环境是采用pure Go resolver的,而在新的失败环境被切换到cgo resolver, 这是因为含有pure Go resolver不支持的options single-request-reopen。

注:Pure Go resolver目前仅支持ndots, timeout, attempts, rotate
https://github.com/golang/go/blob/964639cc338db650ccadeafb7424bc8ebb2c0f6c/src/net/dnsconfig_unix.go

       case "options": // magic options
            for _, s := range f[1:] {
                switch {
                case hasPrefix(s, "ndots:"):
                    n, _, _ := dtoi(s[6:])
                    if n < 0 {
                        n = 0
                    } else if n > 15 {
                        n = 15
                    }
                    conf.ndots = n
                case hasPrefix(s, "timeout:"):
                    n, _, _ := dtoi(s[8:])
                    if n < 1 {
                        n = 1
                    }
                    conf.timeout = time.Duration(n) * time.Second
                case hasPrefix(s, "attempts:"):
                    n, _, _ := dtoi(s[9:])
                    if n < 1 {
                        n = 1
                    }
                    conf.attempts = n
                case s == "rotate":
                    conf.rotate = true
                default:
                    conf.unknownOpt = true
                }
            }

进一步的,我们尝试分析是什么原因导致了新老容器内的resolv.conf的内容变化,发现了原来是最近宿主机ECS的配置文件发生了变化:

  • 失败的环境 - 新创建的ECS:

    # cat /etc/resolv.conf
    # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
    #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
    nameserver 100.100.2.138
    nameserver 100.100.2.136
    options timeout:2 attempts:3 rotate single-request-reopen
  • 成功的环境 - 原来的ECS:

    # cat /etc/resolv.conf
    # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
    #     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
    nameserver 100.100.2.136
    nameserver 100.100.2.138

另一方面,我们也尝试分析为什么切换到cgo resolver之后会产生SIGSEGV的错误,以下这篇文章解释了static link cgo会导致SIGSEGV的错误:
https://tschottdorf.github.io/golang-static-linking-bug

而这个Hyperledger Fabric的bug则指出了Hyperledger Fabric的build(尤其是和getaddrinfo相关方法)正是static link的:
https://jira.hyperledger.org/browse/FAB-6403

至此,我们找到了问题的根源和复盘了整个问题发生的逻辑:

  • 近期新创建的ECS主机中的resolv.conf内容发生了变化 -> 导致Hyperledger Fabric的容器内域名解析从pure Go resolver切换至cgo resolver -> 触发了一个已知的由静态链接cgo导致的SIGSEGV错误 -> 导致Hyperledger Fabric部署失败。

解决方法建议

更新Hyperledger Fabric的docker compose yaml模板,为所有Hyperledger Fabric的节点(如orderer, peer, ca, cli等)添加环境变量GODEBUG=netdns=go以强制使用pure Go resolver

分享到:
评论

相关推荐

    linux下段错误检查sigsegv

    用于检查linux段错误时,定位源码位置

    Obtaining a stack trace in C upon SIGSEGV

    有时候当你的程序崩溃时能获得...下文给出的程序可以做到不用调试器却可以得到程序的堆栈轨迹,和内核给出的堆栈轨迹类似。目前看来,我发现的唯一不足就是编译时需要加上-rdynamic选项,这会使你的程序体积变得很大。

    segmentation fault in linux

    文中以实例回答了常见的一些SIGSEGV问题,例如“为什么函数返回了栈还可以访问?”、“为什么free()后的内存仍然可以使用”、“为什么我遇到的是SIGSEGV而不是SIGILL信号”等。最后笔者结合自己的经验,列举了一些...

    openjdk遇到的https的ssl异常解决方案

    openjdk遇到的https的ssl异常解决方案,提供了两套解决方案

    解决Oracle 9.2.0.6版本数据库由于ORA-07445宕机问题

    1 解决Oracle 9.2.0.6版本数据库由于ORA-07445宕机问题 故障现象: XX网数据库宕机,查看日志发现以下内容: Wed Jun 8 20:24:17 2005 Errors in file /u02/app/oracle/admin/unicom/udump/unicom_ora_661.trc: ORA-...

    Vivado_HLS嵌入式实时图像处理系统的构建与实现_张艳辉

    这个论文详细讲述了Vivado_HLS嵌入式实时图像处理系统的构建与实现,可以提供一些参考

    Android rom开发:app运行异常,报libc: Fatal signal 11 (SIGSEGV) in tid xxx错误

    最近遇到了app在设备上反复挂掉的问题。log如下: 2020-03-07 13:20:24.814 16858-16858/? E/SharedPreferencesImpl: Couldn't create directory for SharedPreferences file /data/user/0/...

    Oracle ORA 07445 evaopn2()+128错误问题的解决方案

    问题描述 Plsql developer执行一段sql报错: 经查alert log详细报错信息为: ORA-07445: exception encountered: core dump [evaopn2()+128] [SIGSEGV] [Address not mapped to object] [0x000000000] [] [] ...

    mysql workbench

    mysql workbench

    os_labs_miet

    理想情况下,应该采取一些步骤自己解决问题。一个好问题的例子: 我编写了一个程序: : 。 我对其进行了编译并尝试执行,但是出现了“无效的内存引用(SIGSEGV)”错误。 我搜索了该错误,但仍然不知道如何解决该...

    欧拉公式求圆周率的matlab代码-Competitive-Programming:该信息库包含针对竞争性编程网站(例如SPOJ,CSES,U

    此外,如果您在此存储库中提供的程序/源代码中发现任何与逻辑错误,语法错误,SIGSEGV,SIGFPE,SIGABRT,NZEC错误有关的错误,请为此创建一个问题。 如果您有更好的算法或解决问题的逻辑方法,那么请为存储库做出...

    适用于 iOS 的 Airbrake 通知器_Objective-C_代码_下载

    Airbrake iOS/Mac OS 通知程序旨在让开发人员即时通知其应用程序中出现的问题。只需在您的项目中添加几行代码和一些额外的文件,您的应用就会在遇到崩溃或异常时自动打电话回家。这些报告直接发送到 Airbrake,您...

    Android集成百度地图

    Android集成百度地图SDK,内有定位,覆盖物,导航,线路绘制等功能

    Oracle数据库常见真实问题处理步骤

    火龙果软件工程技术中心 1解决Oracle9.2.0.6版本数据库由于ORA-07445宕机问题故障现象:XX网数据库宕机,查看日志发现以下内容:WedJun 820:24:172005Errorsinfile/u02/app/oracle/admin/unicom/udump/unicom_ora_...

    p8670579_112010_LINUX.zip

    linux5安装oracle11g--dbca时出现下列错误的解决办法,把包打进linux系统保证好用--里边有打补丁方法readme.TXT An unexpected error has been detected by HotSpot Virtual Machine:## SIGSEGV (0xb) at pc=0x00007...

    DMP-Hooker

    解决c++中崩溃问题,捕捉程序中种种异常,产生dmp信息以方便修改, 适用windows平台。 1 CrashHooker 为异常捕捉模块 2 CrashRptTest 为模拟各种异常模块 【分为主线程和其他线程】 (1)seh (2)C++ terminate() ...

    Linux函数和脚本

    1.条件测试和信号捕获 1.退出状态 2.测试状态 1.文件状态测试 2.变量状态测试 3.字符串和数值状态测试 4.逻辑操作符 3.捕获系统信号 1.系统信号说明 1.1 SIGHUP 2.2 SIGINT 3.3 SIGQUIT 4.4 SIGILL 5.5 SIGTRAP 6.6 ...

    安卓源码截屏

    can't read framebuffer pid=14444, uid=1010这个问题,紧接着就出现了Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 14444 (droid.ScreenCap)这个问题,不知道是什么原因?希望能够解答,谢谢!...

    STX:C ++ 17和C ++ 20错误处理和实用程序扩展

    SIGSEGV , SIGILL和SIGFPE )回溯库适用于嵌入式系统,实时系统,安全关键型系统和操作系统的便携式,适用且易于采用的系统简易调试易于使用且难以滥用的API无异常,无RTTI和无内存分配( no-std )时空确定性错误...

Global site tag (gtag.js) - Google Analytics