Sun JVMJRE jre1.6.0_24segfault NET_Read

问题描述

| 我们的JVM有时会因分段错误而崩溃 感觉就像某种种族条件的生产。 复制设置: -Linux Ubuntu 9.10和Debian 4.x 64位多核AMD上的JRE jre1.6.0_24 -Apache tomcat 6.0.24 ... 6.0.32 使用fastdebug重新编译Java会重现此问题(此gcc -g1)。 但是,它所产生的有用信息并不比我们多 在这里 用debug重新编译Java不会重现问题(这是 gcc -g加上一些-DSOMETHING代码调试标志)。 任何帮助找出这一点的帮助将不胜感激。 使用Oracle 1.6.0_24 jdk生成的核心文件。 gdb出现:
    Program terminated with signal 11,Segmentation fault.
    #0  0x00002aaab7b10666 in NET_Read () from
    /usr/local/jdk1.6.0_24/jre/lib/amd64/libnet.so
好的,所以我的程序集真的很生锈。请记住:
    (gdb) info frame
    Stack level 0,frame at 0x4b3e0040:
     rip = 0x2aaab7b10666 in NET_Read; saved rip 0x2aaab7b0d53b
     called by frame at 0x4b3f0090
             Arglist at 0x4b3dffc8,args:
     Locals at 0x4b3dffc8,Previous frame\'s sp is 0x4b3e0040
     Saved registers:
     rbx at 0x4b3e0008,rbp at 0x4b3e0010,r12 at 0x4b3e0018,r13 at
    0x4b3e0020,r14 at 0x4b3e0028,r15 at 0x4b3e0030,rip at 0x4b3e0038
因此,gdb告诉我们参数列表位于:
    0x4b3dffc8
查看那里的数据:
    (gdb) x/8x 0x4b3dffc8
    0x4b3dffc8:     0x00000000      0x00000000      0x00000000      0x00000000
    0x4b3dffd8:     0x00000000      0x00000000      0x00000000      0x00000000
` 所以那里没有骰子。同样,我的装配可以追溯到第二波ska,所以我 只能认为堆栈有些混乱,或者gcc 优化标志生成使用寄存器作为参数的代码 而不是堆栈? 进入寄存器:
    (gdb) info registers
    rax            0xf2     242
                                                    rbx            0x4      4
    rcx            0x2b73aa8bfed3   47775782534867
    rdx            0x4      4
    rsi            0x4b3e0050       1262354512
            rdi            0xf2     242
    rbp            0x0      0x0
    rsp            0x4b3dffd0       0x4b3dffd0
    r8             0xffc    4092
    r9             0x2b73aa8c61b0   47775782560176
    r10            0x2b73aa8c9f78   47775782575992
    r11            0x2b73aa8b20d0   47775782478032
    r12            0xf2     242
    r13            0xf2     242
    r14            0x2aaabad4b9c8   46912767310280
    r15            0x4      4
    rip            0x2aaab7b10666   0x2aaab7b10666 <NET_Read+22>
    eflags         0x10202  [ IF RF ]
    cs             0x33     51
    ss             0x2b     43
    ds             0x0      0
    es             0x0      0
    fs             0x63     99
    gs             0x0      0
反汇编(在我看来,这是Read + 22的错误):
    0x00002aaab7b10650 <NET_Read+0>:        push   %r15
            0x00002aaab7b10652 <NET_Read+2>:        mov    %rdx,%r15
    0x00002aaab7b10655 <NET_Read+5>:        push   %r14
                            0x00002aaab7b10657 <NET_Read+7>:        push   %r13
    0x00002aaab7b10659 <NET_Read+9>:        mov    %edi,%r13d
    0x00002aaab7b1065c <NET_Read+12>:       push   %r12
    0x00002aaab7b1065e <NET_Read+14>:       push   %rbp
    0x00002aaab7b1065f <NET_Read+15>:       push   %rbx
    0x00002aaab7b10660 <NET_Read+16>:       sub    $0x38,%rsp
    0x00002aaab7b10664 <NET_Read+20>:       test   %edi,%edi
    0x00002aaab7b10666 <NET_Read+22>:       mov    %rsi,0x8(%rsp)
    0x00002aaab7b1066b <NET_Read+27>:       js     0x2aaab7b1067c <NET_Read+44>
    0x00002aaab7b1066d <NET_Read+29>:       lea    1073812(%rip),%rax
     # 0x2aaab7c16908 <fdCount>
    0x00002aaab7b10674 <NET_Read+36>:       cmp    (%rax),%edi
    0x00002aaab7b10676 <NET_Read+38>:       jle    0x2aaab7b1070b <NET_Read+187>
    0x00002aaab7b1067c <NET_Read+44>:       xor    %ebp,%ebp
    0x00002aaab7b1067e <NET_Read+46>:       test   %rbp,%rbp
    0x00002aaab7b10681 <NET_Read+49>:       je     0x2aaab7b106f9 <NET_Read+169>
    0x00002aaab7b10683 <NET_Read+51>:       lea    0x10(%rsp),%r14
    0x00002aaab7b10688 <NET_Read+56>:       callq  0x2aaab7b03dd0 <pthread_self@plt>
    0x00002aaab7b1068d <NET_Read+61>:       mov    %rbp,%rdi
    0x00002aaab7b10690 <NET_Read+64>:       movl   $0x0,0x20(%rsp)
    0x00002aaab7b10698 <NET_Read+72>:       mov    %rax,0x10(%rsp)
    0x00002aaab7b1069d <NET_Read+77>:       callq  0x2aaab7b03f80
    <pthread_mutex_lock@plt>
    0x00002aaab7b106a2 <NET_Read+82>:       mov    %rbp,%rdi
    0x00002aaab7b106a5 <NET_Read+85>:       mov    0x28(%rbp),%rax
    0x00002aaab7b106a9 <NET_Read+89>:       mov    %rax,0x18(%rsp)
    0x00002aaab7b106ae <NET_Read+94>:       mov    %r14,0x28(%rbp)
    0x00002aaab7b106b2 <NET_Read+98>:       callq  0x2aaab7b043b0
    <pthread_mutex_unlock@plt>
    0x00002aaab7b106b7 <NET_Read+103>:      mov    %r13d,%edi
    0x00002aaab7b106ba <NET_Read+106>:      mov    0x8(%rsp),%rsi
    0x00002aaab7b106bf <NET_Read+111>:      xor    %ecx,%ecx
    0x00002aaab7b106c1 <NET_Read+113>:      mov    %r15,%rdx
    0x00002aaab7b106c4 <NET_Read+116>:      callq  0x2aaab7b04160 <recv@plt>
    0x00002aaab7b106c9 <NET_Read+121>:      mov    %rbp,%rdi
    0x00002aaab7b106cc <NET_Read+124>:      mov    %r14,%rsi
    0x00002aaab7b106cf <NET_Read+127>:      mov    %eax,%ebx
    0x00002aaab7b106d1 <NET_Read+129>:      mov    %rax,%r12
    0x00002aaab7b106d4 <NET_Read+132>:      callq  0x2aaab7b11000 <endOp>
    0x00002aaab7b106d9 <NET_Read+137>:      inc    %ebx
    0x00002aaab7b106db <NET_Read+139>:      jne    0x2aaab7b106e7 <NET_Read+151>
    0x00002aaab7b106dd <NET_Read+141>:      callq  0x2aaab7b04380
    <__errno_location@plt>
    0x00002aaab7b106e2 <NET_Read+146>:      cmpl   $0x4,(%rax)
    0x00002aaab7b106e5 <NET_Read+149>:      je     0x2aaab7b10688 <NET_Read+56>
    0x00002aaab7b106e7 <NET_Read+151>:      mov    %r12d,%eax
    0x00002aaab7b106ea <NET_Read+154>:      add    $0x38,%rsp
    0x00002aaab7b106ee <NET_Read+158>:      pop    %rbx
    0x00002aaab7b106ef <NET_Read+159>:      pop    %rbp
    0x00002aaab7b106f0 <NET_Read+160>:      pop    %r12
    0x00002aaab7b106f2 <NET_Read+162>:      pop    %r13
            0x00002aaab7b106f4 <NET_Read+164>:      pop    %r14
            0x00002aaab7b106f6 <NET_Read+166>:      pop    %r15
            0x00002aaab7b106f8 <NET_Read+168>:      retq
            0x00002aaab7b106f9 <NET_Read+169>:      callq  0x2aaab7b04380
    <__errno_location@plt>
    0x00002aaab7b106fe <NET_Read+174>:      movl   $0x9,(%rax)
    0x00002aaab7b10704 <NET_Read+180>:      mov    $0xffffffff,%eax
    0x00002aaab7b10709 <NET_Read+185>:      jmp    0x2aaab7b106ea <NET_Read+154>
    0x00002aaab7b1070b <NET_Read+187>:      movslq %edi,%rax
    0x00002aaab7b1070e <NET_Read+190>:      lea    (%rax,%rax,2),%rbp
    0x00002aaab7b10712 <NET_Read+194>:      lea    1073639(%rip),%rax
     # 0x2aaab7c16900 <fdTable>
    0x00002aaab7b10719 <NET_Read+201>:      shl    $0x4,%rbp
    0x00002aaab7b1071d <NET_Read+205>:      add    (%rax),%rbp
    ---Type <return> to continue,or q <return> to quit---
    0x00002aaab7b10720 <NET_Read+208>:      jmpq   0x2aaab7b1067e <NET_Read+46>
    0x00002aaab7b10725 <NET_Read+213>:      data16
    0x00002aaab7b10726 <NET_Read+214>:      data16
    0x00002aaab7b10727 <NET_Read+215>:      data16
    0x00002aaab7b10728 <NET_Read+216>:      nop
    0x00002aaab7b10729 <NET_Read+217>:      data16
    0x00002aaab7b1072a <NET_Read+218>:      data16
    0x00002aaab7b1072b <NET_Read+219>:      data16
    0x00002aaab7b1072c <NET_Read+220>:      nop
    0x00002aaab7b1072d <NET_Read+221>:      data16
    0x00002aaab7b1072e <NET_Read+222>:      data16
    0x00002aaab7b1072f <NET_Read+223>:      nop
查看NETRead的源代码:
    jdk/src/solaris/native/java/net/linux_close.c

    *snip*
    /*
             * Macro to perform a blocking IO operation. Restarts
     * automatically if interrupted by signal (other than
             * our wakeup signal)
     */
    #define BLOCKING_IO_RETURN_INT(FD,FUNC) {      \\
       int ret;                                    \\
       threadEntry_t self;                         \\
               fdEntry_t *fdEntry = getFdEntry(FD);        \\
               if (fdEntry == NULL) {                      \\
           errno = EBADF;                          \\
           return -1;                              \\
       }                                           \\
       do {                                        \\
           startOp(fdEntry,&self);                \\
           ret = FUNC;                             \\
           endOp(fdEntry,&self);                  \\
       } while (ret == -1 && errno == EINTR);      \\
       return ret;                                 \\
    }

    int NET_Read(int s,void* buf,size_t len) {
       BLOCKING_IO_RETURN_INT( s,recv(s,buf,len,0) );
    }
谢谢。     

解决方法

        我们的生产服务器上存在相同的问题。问题基本上是隐藏在segfault中的JNI代码中的堆栈溢出:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7059899 尝试jstack从VM生成的核心文件中提取线程转储,然后查找无限循环。     ,        是getFdEntry是宏还是内联?我会看看那里。基于汇编程序代码转储,seg错误发生在第一个分支之前,即初始堆栈操作之后,这使它似乎出现在getFdEntry中。另外,鉴于对read的调用包含在看起来像是锁定/解锁操作的可疑对象中,我认为您对竞争状况的怀疑可能很好。没有看到其余的源代码,这很难说,但是我最好的猜测是getFdEntry是一个内联函数,其线程安全性不如应有的安全。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...