Что может быть причиной сигнала BUS_ADRERR
во время dlopen()
? Я получаю много таких отчетов о сбоях от разных пользователей.
Некоторые примечания:
si_addr
адрес сигнальных точек в загруженной библиотеке. Это действительно озадачивает меня.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 [email protected]
j java.lang.ClassLoader$NativeLibrary.load()Z+53 [email protected]
j java.lang.ClassLoader$NativeLibrary.loadLibrary(Ljava/lang/Class;Ljava/lang/String;Z)Z+216 [email protected]
j java.lang.ClassLoader.loadLibrary0(Ljava/lang/Class;Ljava/io/File;)Z+46 [email protected]
j java.lang.ClassLoader.loadLibrary(Ljava/lang/Class;Ljava/lang/String;Z)V+48 [email protected]
j java.lang.Runtime.load0(Ljava/lang/Class;Ljava/lang/String;)V+57 [email protected]
j java.lang.System.load(Ljava/lang/String;)V+7 [email protected]
<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)
SIGBUS
очень редко встречается в системах Linux / x86.
Один из случаев, когда это происходит, — это когда файл mmap
ed усекается. Из карта человека:
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).
Our application extracts the libraries from ZIP before loading them.
Дикая догадка: у вас есть состояние гонки, когда вы можете выполнять это извлечение из двух отдельных потоков одновременно.
Первый поток извлекает libswt-gtk-4922r22.so
из ZIP-архива и dlopen
s его. dlopen
mmap
s файл, перемещает его и вызывает инициализатор библиотеки.
Во время работы инициализатора библиотеки второй поток решает, что библиотеку необходимо извлечь (это ошибка), и усекает файл .so
перед записью в него нового (идентичного) содержимого. Как только truncate завершится, первый поток (все еще работающий инициализатор библиотеки) уничтожается с помощью SIGBUS
.
Обычное исправление состоит в том, чтобы убедиться, что «проверить, существует ли файл, извлечь, если нет» в критическом разделе.
Спасибо, почти так и произошло. Я исправил ошибку вчера, но вы быстрее разместили ответ :) С той лишь разницей, что она была вызвана быстрым запуском двух процессов. Сначала увидел, что библиотека отсутствует, начал ее распаковывать, второй увидел частичную библиотеку на диске, загрузил ее и разбился. Критические разделы здесь не помогут, но я решил проблему, извлекая во временный файл и перемещая его, когда он будет полностью записан.