BUS_ADRERR в dlopen () - PullRequest
       15

BUS_ADRERR в dlopen ()

0 голосов
/ 09 апреля 2019

Что может вызывать сигнал BUS_ADRERR во время dlopen()? Я получаю много таких отчетов о сбоях от разных пользователей.

Некоторые заметки:

  1. Это происходит с разными библиотеками (наше приложение использует несколько)
  2. si_addr адрес сигнальных точек в загруженной библиотеке. Это действительно озадачивает меня.
  3. Системной памяти всегда достаточно.
  4. Пользователи говорят, что приложение будет запускаться правильно со второй попытки.
  5. Наше приложение извлекает библиотеки из ZIP перед загрузкой.
  6. Изучение journalctl ничего интересного не показывает.

Типичный отчет о сбое (генерируется Java):

Stack: [0x00007f284919b000,0x00007f284939c000],  sp=0x00007f2849397258,  free space=2032k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [ld-linux-x86-64.so.2+0x1fa6f]
C  [ld-linux-x86-64.so.2+0x8ffc]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  java.lang.ClassLoader$NativeLibrary.load0(Ljava/lang/String;Z)Z+0 java.base@10.0.1
j  java.lang.ClassLoader$NativeLibrary.load()Z+53 java.base@10.0.1
j  java.lang.ClassLoader$NativeLibrary.loadLibrary(Ljava/lang/Class;Ljava/lang/String;Z)Z+216 java.base@10.0.1
j  java.lang.ClassLoader.loadLibrary0(Ljava/lang/Class;Ljava/io/File;)Z+46 java.base@10.0.1
j  java.lang.ClassLoader.loadLibrary(Ljava/lang/Class;Ljava/lang/String;Z)V+48 java.base@10.0.1
j  java.lang.Runtime.load0(Ljava/lang/Class;Ljava/lang/String;)V+57 java.base@10.0.1
j  java.lang.System.load(Ljava/lang/String;)V+7 java.base@10.0.1
<snip>

siginfo: si_signo: 7 (SIGBUS), si_code: 2 (BUS_ADRERR), si_addr: 0x00007f27deec7880

<snip>

7f27dec43000-7f27decc1000 r-xp 00000000 08:08 1054117 <snip>/libswt-gtk-4922r22.so
7f27decc1000-7f27deec0000 ---p 0007e000 08:08 1054117 <snip>/libswt-gtk-4922r22.so
7f27deec0000-7f27deec8000 rw-p 0007d000 08:08 1054117 <snip>/libswt-gtk-4922r22.so
7f27deec8000-7f27deecb000 r-xp 00285000 08:08 1054117 <snip>/libswt-gtk-4922r22.so

<snip>

Memory: 4k page, physical 3902428k(1540768k free), swap 3998716k(3998716k free)

1 Ответ

1 голос
/ 10 мая 2019

SIGBUS очень редко встречается в системах Linux / x86.

Один из случаев, когда это происходит, - это когда mmap ed файл обрезается. От man mmap :

SIGBUS Attempted access to a portion of the buffer that does not
       correspond to the file (for example, beyond the end of the
       file, including the case where another process has truncated
       the file).

Наше приложение извлекает библиотеки из ZIP перед загрузкой.

Дикая догадка: у вас есть состояние гонки, где вы можете выполнить это извлечение из двух отдельных потоков одновременно.

Первый поток извлекает libswt-gtk-4922r22.so из архива ZIP и dlopen s. dlopen mmap s файл, перемещает его и вызывает инициализатор библиотеки.

Во время работы инициализатора библиотеки второй поток решает, что библиотека должна быть извлечена (это ошибка), и обрезает файл .so перед записью в него нового (идентичного) содержимого. Как только truncate завершится, первый поток (все еще работающий с инициализатором библиотеки) будет уничтожен с SIGBUS.

Обычное исправление заключается в том, чтобы убедиться в том, что «проверка того, что файл существует, извлечение, если нет», выполняется в критическом разделе.

...