簡體   English   中英

多線程進程中的處理程序未捕獲 SIGSEGV 信號

[英]SIGSEGV signal not caught by handler in multi threaded process

我正在開發一個 Vulkan 層,該層攔截所有 Vulkan 調用並將它們寫入文件中。 在處理映射到用戶空間的設備內存時,該層通過使用mprotect保護內存區域來檢測用戶的讀取和寫入。

這個想法是,當用戶向vkMapMemory請求一些內存時,該層使用帶有PROT_READ | PROT_WRITEmmap分配內存。 設置PROT_READ | PROT_WRITE標志,使用sigactionSIGSEGV設置信號處理程序, mprotect防止讀取和寫入,並將基指針返回給用戶。 任何訪問都將觸發SIGSEGV ,而處理程序會負責其余的工作。 到目前為止,一切都很好。

我正在處理的問題是,有 2 個線程分配和訪問所述內存區域,並且當其中一個線程訪問所述內存區域之一時,生成的SIGSEGV不定向到處理程序,而是終止具有分段錯誤的應用程序。 另一個線程按預期工作。

貝婁是崩潰前發生的事情的摘錄:

[59588] AddExceptionHandler() -> sigaction SIGSEGV *******************
[59588] SetMemoryProtection() mprotect: ptr: 0x7fec0819d000 - 0x7fec0839d000 size: 2097152 mask: 0x0
[59588] MapMemory <-- *ppData: 0x7fec0819d000
[59588] PageGuardExceptionHandler()
  [59588] HandleGuardPageViolation() address: 0x7fec0819d000 is_write: 1 clear_guard: 1
  [59588] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59588] SetMemoryProtection() mprotect: ptr: 0x7fec0819d000 - 0x7fec0819e000 size: 4096 mask: 0x3
[59588] PageGuardExceptionHandler() <-- (handled: true)
[59588] MapMemory(memory: 0x5575f2d5cb20 size: 2097152)
[59588] mmap: 0x7fec013fb000 - 0x7fec015fb000 size: 2097152
[59588] SetMemoryProtection() mprotect: ptr: 0x7fec013fb000 - 0x7fec015fb000 size: 2097152 mask: 0x0
[59588] MapMemory <-- *ppData: 0x7fec013fb000
[59588] PageGuardExceptionHandler()
  [59588] HandleGuardPageViolation() address: 0x7fec013fb000 is_write: 1 clear_guard: 1
  [59588] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59588] SetMemoryProtection() mprotect: ptr: 0x7fec013fb000 - 0x7fec013fc000 size: 4096 mask: 0x3
[59588] PageGuardExceptionHandler() <-- (handled: true)
[59588] AllocateMemory(size: 4194304) *pMemory: 0x5575f2f5c080
[59588] AllocateMemory(size: 537600) *pMemory: 0x5575f2f5c710

Test case 'dEQP-GLES31.functional.shaders.opaque_type_indexing.sampler.dynamically_uniform.geometry.samplercubearray'..
[59607] AllocateMemory(size: 2097152) *pMemory: 0x7febe80016c0
[59607] MapMemory(memory: 0x7febe80016c0 size: 2097152)
[59607] mmap: 0x7fec007fa000 - 0x7fec009fa000 size: 2097152
[59588] PageGuardExceptionHandler()
  [59588] HandleGuardPageViolation() address: 0x7fec0143b9e0 is_write: 1 clear_guard: 1
  [59588] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59588] SetMemoryProtection() mprotect: ptr: 0x7fec0143b000 - 0x7fec0143c000 size: 4096 mask: 0x3
[59588] PageGuardExceptionHandler() <-- (handled: true)
[59588] PageGuardExceptionHandler()
  [59588] HandleGuardPageViolation() address: 0x7fec0829d000 is_write: 1 clear_guard: 1
  [59588] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59588] SetMemoryProtection() mprotect: ptr: 0x7fec0829d000 - 0x7fec0829e000 size: 4096 mask: 0x3
[59588] PageGuardExceptionHandler() <-- (handled: true)
[59607] SetMemoryProtection() mprotect: ptr: 0x7fec007fa000 - 0x7fec009fa000 size: 2097152 mask: 0x0
[59607] MapMemory <-- *ppData: 0x7fec007fa000
[59607] util_copy_rect() 1 src: 0x5575f2e6c468 dst: 0x7fec007fa000 size: 4
Segmentation fault (core dumped)

所以最后可以看到第二個線程進入游戲,請求其中一個內存區域,它被第一個線程中發生的SIGSEGV的第一個線程的信號處理程序中斷,然后繼續mprotect新區域,訪問它但不調用處理程序。

使用 Valgrind 運行時,崩潰前發生的事情順序略有不同:

[59840] PageGuardExceptionHandler()
  [59840] HandleGuardPageViolation() address: 0x14e08000 is_write: 1 clear_guard: 1
  [59840] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59840] SetMemoryProtection() mprotect: ptr: 0x14e08000 - 0x14e09000 size: 4096 mask: 0x3
[59840] PageGuardExceptionHandler() <-- (handled: true)
[59840] PageGuardExceptionHandler()
  [59840] HandleGuardPageViolation() address: 0x14ac8000 is_write: 1 clear_guard: 1
  [59840] 1107:HandleGuardPageViolation() -> SetMemoryProtection()
  [59840] SetMemoryProtection() mprotect: ptr: 0x14ac8000 - 0x14ac9000 size: 4096 mask: 0x3
[59840] PageGuardExceptionHandler() <-- (handled: true)
[59881] AllocateMemory(size: 2097152) *pMemory: 0xe695c80
[59881] MapMemory(memory: 0xe695c80 size: 2097152)
[59881] mmap: 0x161c9000 - 0x163c9000 size: 2097152
[59881] SetMemoryProtection() mprotect: ptr: 0x161c9000 - 0x163c9000 size: 2097152 mask: 0x0
[59881] MapMemory <-- *ppData: 0x161c9000
[59881] util_copy_rect() 1 src: 0xec7a0d8 dst: 0x161c9000 size: 4
==59840== 
==59840== Process terminating with default action of signal 11 (SIGSEGV)
==59840==  Bad permissions for mapped region at address 0x161C9000
==59840==    at 0x4842B33: memmove (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==59840==    by 0x5EFB4CE: util_copy_box (u_surface.c:78)
==59840==    by 0x611CA0B: u_default_texture_subdata (u_transfer.c:71)
==59840==    by 0x5F05BCC: tc_call_texture_subdata (u_threaded_context.c:2529)
==59840==    by 0x5F01031: tc_batch_execute (u_threaded_context.c:213)
==59840==    by 0x584334B: util_queue_thread_func (u_queue.c:313)
==59840==    by 0x5842F5A: impl_thrd_routine (threads_posix.h:87)
==59840==    by 0x49A7608: start_thread (pthread_create.c:477)
==59840==    by 0x4E51132: clone (clone.S:95)

在這種情況下,唯一的區別是第二個線程沒有被中斷。

使用taskset 1運行該過程,這基本上使所有事情都按順序進行,從而使問題消失。

我不明白為什么第二個線程的SIGSEGV沒有被處理程序捕獲

編輯:我忘了提到的一件重要的事情是 mesa 庫也在圖片中。 日志來自在 zink 上運行的 gles 應用程序(cts 測試),該應用程序將其轉換為 Vulkan 調用。 如果我沒記錯的話,多個線程是由 mesa 生成的。

有點想通了我的問題。 不知何故SIGSEGV被阻止。 我不確定這是如何發生的,因為在sigprocmask上使用 gdb 設置斷點永遠不會觸發。

編輯:它被pthread_sigmask阻塞

每次重新啟用它:

sigset_t x;
sigemptyset(&x);
sigaddset(&x, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &x, NULL);

解決了我的問題(並可能創建另一個問題)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM