gdb在Alpine Linux上调试OpenJDK java失败;线程接收信号?,未知信号“;

gdb在Alpine Linux上调试OpenJDK java失败;线程接收信号?,未知信号“;,java,gdb,signals,alpine,musl,Java,Gdb,Signals,Alpine,Musl,我在尝试使用gdb在Alpine Linux上调试OpenJDK java时遇到了困难——有人成功地做到了吗 当尝试在gdb中调试java时,例如,gdb java和r-version,它会立即失败: Thread 1 "java" recieved signal ?, Unknown signal. __cp_end () at src/thread/x86_64/syscall_cp.s:29 我搜索了又搜索,但找不到任何关于Alpine上OpenJDK调试的参考或解决方案 在其他平台(m

我在尝试使用gdb在Alpine Linux上调试OpenJDK java时遇到了困难——有人成功地做到了吗

当尝试在gdb中调试java时,例如,
gdb java
r-version
,它会立即失败:

Thread 1 "java" recieved signal ?, Unknown signal.
__cp_end () at src/thread/x86_64/syscall_cp.s:29
我搜索了又搜索,但找不到任何关于Alpine上OpenJDK调试的参考或解决方案

在其他平台(macOS Sierra,MinGW)上看到的处理相同gdb错误的其他线程表明,
接收到的信号?、未知信号
可能由各种原因造成,包括、、和其他应用程序错误

外部GDB,java工作没有任何问题,GDB对调试C++程序很有效。我正在运行Alpine V3.8

我尝试过的事情:

  • 不同的gdb版本(
    8.0.1-r6
    8.0.1-r3
    7.12.1-r1
  • 不同的OpenJDK版本(
    1.8.0_171
    1.7.0_181
  • 从不同的shell(
    /bin/ash
    /bin/bash
    )运行,有和没有
    sudo
  • .gdbinit
    中禁用信号停止功能:
    处理SIGSEGV nostop noprint pass
    ,对于
    SIGPPIPE
    SIGHUP
    SIGFPE
    SIG34
    也一样
  • 在shell关闭时设置启动
    添加到
    .gdbinit
谢谢你的帮助

编辑:

下面是抛出未知信号的完整堆栈,这会导致JVMInit失败:

(gdb)r-版本
启动程序:/usr/lib/jvm/java-1.8-openjdk/bin/java-version
进程16214正在执行新程序:/usr/lib/jvm/java-1.8-openjdk/bin/java
[新LWP 16219]
线程1“java”接收到信号?,未知信号。
__位于src/thread/x86\u 64/syscall\u cp.s:29的cp\u end()
29 src/thread/x86_64/syscall_cp.s:没有这样的文件或目录。
(gdb)信息线程
Id目标Id帧
*src/thread/x86\u 64/syscall\u cp.s:29处的1 LWP 16214“java”\u cp\u end()
2 LWP 16219“java”同步调用(func=func@entry=0x7ffff7da2662,ctx=ctx@entry=0x7ffff7ff4720)
在src/thread/synccall.c:143
(gdb)在哪里
#src/thread/x86\u 64/syscall\u cp.s:29处的0\uu cp\u end()
#系统调用中的1 0x00007ffff7dbed2d(nr=202,u=,v=,w=,x=,
y=,z=0)在src/thread/pthread_cancel.c:35
#2 0x00007FF7DBE350英寸时间等待cp(地址=addr@entry=0x7ffff7ff4b20,val=16219,时钟=clk@entry=0,在=at@entry=0x0,priv=priv@entry=0)
在src/thread/_timedwait.c:31
#3 0x00007FF7FF7DBFDC4在线程时间连接np中(t=0x7ffff7ff4ae8,res=res@entry=0x7FFFFFA348,在=at@entry=0x0)
在src/thread/pthread_join.c处:16
#4 0x00007FF7DBFE02在线程连接中(t=,res=res@entry=0x7FFFFFA348)位于src/thread/pthread_join.c:27
#5 0x00007FF7B6695E在ContinueInNewThread0(continuence)中=continuation@entry=0x7ffff7b61a60,堆栈大小=1048576,
args=args@entry=0x7FFFFFA3E0)
在/home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/solaris/bin/java_md_solinux.c:1046
#6 0x00007FF7B634A4连续连接线程(ifn=ifn@entry=0x7FFFFFA4F0,threadStackSize=,argc=1,
argv=,模式=mode@entry=841574793,什么=what@entry=0x0,ret=0)
在/home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/share/bin/java.c:2024
#JVMInit中的7 0x00007FF7B66A08(ifn=ifn@entry=0x7FFFFFA4F0,threadStackSize=,argc=,
argv=,mode=841574793,mode@entry=0,什么=what@entry=0x0,ret=)
在/home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/solaris/bin/java_md_solinux.c:1093
#JLI_发布中的8 0x00007FF7B63E30(argc=,argv=,jargc=,jargv=,
appclassc=1,appclassv=0x0,fullversion=0x554843“1.8.0_171-b11”,dotversion=0x55483F“1.8”,pname=0x55483A“java”,
lname=0x554832“openjdk”,javaargs=0'\000',cpwildcard=1'\001',javaw=0'\000',ergo=0)
在/home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/share/bin/java.c:304
#main中的9 0x0000554691(argc=,argv=)
at/home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/share/bin/main.c:125
(gdb)
与此堆栈跟踪匹配的musl源文件:

#0  __synccall (func=func@entry=0x7ffff7da2662 <do_setrlimit>, ctx=ctx@entry=0x7ffff7ff4720) at src/thread/synccall.c:48
#1  0x00007ffff7da26a1 in setrlimit (resource=resource@entry=7, rlim=rlim@entry=0x7ffff7ff4750) at src/misc/setrlimit.c:42
#2  0x00007ffff73bd1fe in os::init_2 ()
    at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/os/linux/vm/os_linux.cpp:5096
#3  0x00007ffff746177d in Threads::create_vm (args=0x7ffff7ff4a20, canTryAgain=canTryAgain@entry=0x7ffff7ff4987)
    at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3361
#4  0x00007ffff729cd48 in JNI_CreateJavaVM (vm=0x7ffff7ff4a10, penv=0x7ffff7ff4a18, args=<optimized out>)
    at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/share/vm/prims/jni.cpp:5221
#5  0x00007ffff7b61b0b in InitializeJVM (ifn=<synthetic pointer>, penv=0x7ffff7ff4a18, pvm=0x7ffff7ff4a10)
    at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/share/bin/java.c:1231
#6  JavaMain (_args=<optimized out>)
  • 1:
  • 2:
  • 3、4:
OpenJDK源代码:

  • 7:

JVMInit
通过调用
ContinueInNewThread
尝试创建
JavaMain
本机线程,该线程调用
ContinueInNewThread0(JavaMain,threadStackSize,(void*)和args)
,并在那里爆炸;DR:问题在于GDB缺乏对内部musl信号的支持,如本文所述。

这里提供了一个快速、脏补丁的GDB:

补丁提交:

使用补丁,信号正确识别为SIGSYNCCALL。
然后,可以使用
handle SIGSYNCCALL nostop noprint pass将其屏蔽


谢天谢地,我想出了一个解决办法
调试Alpine OpenJDK java时的gdb崩溃可以通过以下方式进行:

  • 启动gdb
  • break os::init_2
  • 使用所需的命令行参数运行java
  • 当到达断点时,
    设置MaxFDLimit=0
  • 继续,并正常调试
我已经用OpenJDK 8和11 early access测试了解决方案,因此它很可能也适用于OpenJDK 9和10

不幸的是,此解决方案的范围非常有限:

  • 它只在JDK有调试符号的情况下工作——无论是本地调试OpenJDK构建还是使用
    openjdk8 dbg
    debug symbols包
  • 它只适用于命令行gdb,不适用于CLion和eclipsecdt等gdb前端
摘要:

#0 __synccall (func=func@entry=0x7ffff7da2662 <do_setrlimit>, ctx=ctx@entry=0x7ffff7ff4720) at src/thread/synccall.c:48 #1 0x00007ffff7da26a1 in setrlimit (resource=resource@entry=7, rlim=rlim@entry=0x7ffff7ff4750) at src/misc/setrlimit.c:42 #2 0x00007ffff73bd1fe in os::init_2 () at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/os/linux/vm/os_linux.cpp:5096 #3 0x00007ffff746177d in Threads::create_vm (args=0x7ffff7ff4a20, canTryAgain=canTryAgain@entry=0x7ffff7ff4987) at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/share/vm/runtime/thread.cpp:3361 #4 0x00007ffff729cd48 in JNI_CreateJavaVM (vm=0x7ffff7ff4a10, penv=0x7ffff7ff4a18, args=<optimized out>) at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/hotspot/src/share/vm/prims/jni.cpp:5221 #5 0x00007ffff7b61b0b in InitializeJVM (ifn=<synthetic pointer>, penv=0x7ffff7ff4a18, pvm=0x7ffff7ff4a10) at /home/buildozer/aports/community/openjdk8/src/icedtea-3.8.0/openjdk/jdk/src/share/bin/java.c:1231 #6 JavaMain (_args=<optimized out>)

int setrlimit(int resource, const struct rlimit *rlim)
{
    struct ctx c = { .res = resource, .rlim = rlim, .err = -1 };
    __synccall(do_setrlimit, &c);
    if (c.err) {
        if (c.err>0) errno = c.err;
        return -1;
    }
    return 0;
}
r = -__syscall(SYS_tgkill, pid, tid, SIGSYNCCALL);
  if (MaxFDLimit) {
    // set the number of file descriptors to max. print out error
    // if getrlimit/setrlimit fails but continue regardless.
    struct rlimit nbr_files;
    int status = getrlimit(RLIMIT_NOFILE, &nbr_files);
    if (status != 0) {
      if (PrintMiscellaneous && (Verbose || WizardMode))
        perror("os::init_2 getrlimit failed");
    } else {
      nbr_files.rlim_cur = nbr_files.rlim_max;
      status = setrlimit(RLIMIT_NOFILE, &nbr_files);
      if (status != 0) {
        if (PrintMiscellaneous && (Verbose || WizardMode))
          perror("os::init_2 setrlimit failed");
      }
    }
  }