#java #cpp #jni #solaris
bash-3.00$ uname -a SunOS x2001 5.10 Generic_142910-17 i86pc i386 i86pc bash-3.00$ gcc --version gcc (GCC) 4.4.2 Copyright (C) 2009 Free Software Foundation, Inc. This is free software; see the source for copying conditions. Написан код на Java и c++ (с использованием JNI). Но когда вызывается исключение, обработка не попадает в свой catch-обработчик, а вызывается сразу системный и приложение падает в корку. Однако тот же самый код прекрасно работает на Linux 64bit, SPARC 64bit и i386 32bit. Проблема возникает при попытке запуска под Java 8 (по дефолту только 64 бита поддерживается) на Intel SunOs. Флаг -m64 был добавлен в Makefile, и библиотека была добавлена в LD_PRELOAD_64 и LD_LIBRARY_PATH_64 (и также в LD_PRELOAD+LD_LIBRARY_PATH). Java успешно запускается и вызывает нативную функцию Java_com_jnetx_usw_chp_CHPMain_start(), но падает при вызове throw (см. код, лог и trace ниже): INF:17:59:33.20:CHP main(27): CHPMain.run: ok load chp library. Start it... NOT:17:59:33.22:CHP main(27): CHPMain.run: -> chp.start Wed Nov 8 17:59:34 CHP::startTest : cycle = 1 Wed Nov 8 17:59:35 CHP::startTest : cycle = 2 Wed Nov 8 17:59:35 Try cause Exception... # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x0000000000012ab5, pid=10081, tid=0x0000000000000026 # # JRE version: Java(TM) SE Runtime Environment (8.0_121-b13) (build 1.8.0_121-b13) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode solaris-amd64 compressed oops) # Problematic frame: # C 0x0000000000012ab5 # # Core dump written. Default location: /home/kcc_64/x2001/bin/core or core.10081 # # An error report file with more information is saved as: # /home/kcc_64/x2001/bin/hs_err_pid10081.log # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # Код был упрощен до одного потока, который через х секнерит исключение: JNIEXPORT void JNICALL Java_com_jnetx_usw_chp_CHPMain_start (JNIEnv *env, jobject jobj, jint trc_level,jobjectArray j_argv,jobject chp_main,jobject chp_smp) { chp = new CHP(); chp->startTest(); } void CHP::startTest() { int t = 1; while (true) { try { poll(NULL, 0, 1000); fprintf(stderr, "%s CHP::startTest : cycle = %d\n", getTime(), t++); if ( 3 == t ) { fprintf(stderr, "%s : Try generate Exception... \n", getTime()); throw 20; } } catch (const int & e) { fprintf(stderr, "%s : Catch, e = %d\n", getTime(), e); break; } catch (...) { fprintf(stderr, "%s : Catch unknown exception...\n", getTime()); break; } } fprintf(stderr, "%s : CHP::startTest : End thread, exit\n", getTime()); } И ещё вопрос. Почему обработка попадает не в catch блок а сразу в __cxa_throw()? pflags core /38: flags = DETACH sigmask = 0xfffffeff,0x0000ffff cursig = SIGABRT pstack core fffffd7fff291aea _lwp_kill () + a fffffd7fff236c39 raise () + 19 fffffd7fff215bb0 abort () + 90 ... fffffd7ffe9d0343 JVM_handle_solaris_signal () + 8d7 fffffd7ffe9c8617 signalHandler () + 2f fffffd7fff28c2e6 __sighndlr () + 6 fffffd7fff280bc2 call_user_handler () + 252 fffffd7fff280dee sigacthandler (b, fffffd7f7e2f5208, fffffd7f7e2f4ea0) + ee --- called from signal handler with signal 11 (SIGSEGV) --- 0000000000013dd5 ???????? () + 28000d930d5 fffffd7fff2904d9 _SUNW_Unwind_RaiseException () + 46 fffffd7f7dea2c53 __cxa_throw () + 9b !!!!!!!!! fffffd7f7f213310 _ZN3CHP9startTestEv () + 190 fffffd7fee215a14 * com/jnetx/usw/chp/CHPMain.start(I[Ljava/lang/String;Lcom/jnetx/usw/chp/CHPMain;Lcom/jnetx/usw/chp/CHPSmp;)V+0 fffffd7fee2083b6 * com/jnetx/usw/chp/CHPMain.run([Ljava/lang/String;Lcom/jnetx/usw/chp/CHPUpdateListener;)V+563 (line 377) fffffd7fee2083b6 * com/jnetx/usw/chp/CHPProvider$1.run()V+20 (line 374) fffffd7fee2007a7 * com/jnetx/usw/chp/CHPProvider$1.run()V+17760 fffffd7ffe4c10ff __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ () + 8d7 fffffd7ffe4bcd3c __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_pnGSymbol_5pnRJavaCallArguments_pnGThread__v_ () + 424 fffffd7ffe4bd124 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_pnGSymbol_6pnGThread__v_ () + 60 fffffd7ffe64030c __1cMthread_entry6FpnKJavaThread_pnGThread__v_ () + b8 fffffd7ffebd9679 __1cKJavaThreadDrun6M_v_ () + 5e1 fffffd7ffe9bdc85 java_start () + 175 fffffd7fff28bfbb _thr_setup () + 5b fffffd7fff28c1e0 _lwp_start () Компоновка тестового приложения: g++ -g -O2 -m64 -DSOLARIS -DSUNI386 -m64 -D_REENTRANT -fPIC -DTSD -Wall -Wextra -std=c++0x -shared -o libchp.so ../tmp/memtest.o -L../tmp -lpthread -lrt -lsocket -lposix4 -lumem -ldemangle -lrt -bash-3.00$ ldd libchp.so libstdc++.so.6 => /usr/local/gcc4/lib/amd64/libstdc++.so.6 libgcc_s.so.1 => /usr/local/gcc4/lib/amd64/libgcc_s.so.1 Библиотеки, загруженные процессом java lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 nfs.311.1559.269661 -> /home/kcc_64/x2001/lib/native/sunos/i386/libchp.so ... lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.233011 -> /opt/omni/library/libgcc_s.so.1 lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.233028 -> /opt/omni/library/libstdc++.so.6 lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.262550 -> /usr/jdk1.8.0_121/jre/lib/amd64/server/libjvm.so lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.3355 -> /usr/lib/amd64/libCrun.so.1 ... lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.9059 -> /lib/amd64/libmd.so.1 lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.9061 -> /lib/amd64/libmp.so.2 lrwxrwxrwx 1 vb rnd1 0 Nov 9 11:03 ufs.30.0.9062 -> /lib/amd64/libnsl.so.1
Ответы
Ответ 1
Проблема была решена: Существует известная проблема с небольшим несоответствием в ABI между libgcc_s.so: _Unwind_RaiseException и Solaris libc.so: _Unwind_RaiseException. Привязаться (binding) к символам среды выполнения GCC вначале приведет к тому что они загрузятся до времени выполнения Solaris, и все будет работать хорошо. Простое добавление к нашей общей библиотеки ссылки при линковке не помогло. ABI - англ. application binary interface, двоичный (бинарный) интерфейс приложений — набор соглашений для доступа приложения к операционной системе и другим низкоуровневым сервисам, спроектированный для переносимости исполняемого кода между машинами, имеющими совместимые ABI. There is a known issue with a slight mismatch in the ABI between these two (libgcc_s.so: _Unwind_RaiseException and Solaris libc.so: _Unwind_RaiseException). Binding symbols to the GCC runtime first causes it to be loaded before the Solaris runtime, and everything works out well. But, simply adding this explicitly to our shared library link line did not help anything. поэтому простой воркэраунд для этой проблемы: LD_PRELOAD=/usr/sfw/lib/amd64/libgcc_s.so Главная причина была в версии gcc, я использовал версию 4.4, а эта бага была исправлена в версии 4.9 Смешивание раскрутки стэка в libc и libgcc_s на 64-bit Solaris 10+/x86 приводит к краху
Комментариев нет:
Отправить комментарий