[英]How is the signal mask set in sys_rt_sigreturn?
我有以下 C 程序,比如signal.c
:
#define _GNU_SOURCE
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static void *func(void *arg) {
sleep(3);
}
int main(void) {
pthread_t td;
pthread_create(&td, 0, func, NULL);
pthread_cancel(td);
pthread_join(td, NULL);
return 0;
}
該程序使用 musl-gcc 編譯,這意味着它使用 musl-libc。
我想知道這個程序使用的系統調用實際上是如何工作的,所以我用strace
檢查了程序,主要結果是:
[pid 14736] execve("./signal", ["./signal"], 0x55b68a817448 /* 72 vars */) = 0
[pid 14736] arch_prctl(ARCH_SET_FS, 0x603118) = 0
[pid 14736] set_tid_address(0x603330) = 14736
[pid 14736] rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0
[pid 14736] mmap(NULL, 143360, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa528201000
[pid 14736] mprotect(0x7fa528203000, 135168, PROT_READ|PROT_WRITE) = 0
[pid 14736] rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
[pid 14736] clone(child_stack=0x7fa528223ed8, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0x400000, parent_tidptr=0x7fa528223f58, tls=0x7fa528223f20, child_tidptr=0x603330) = 14737
[pid 14736] rt_sigprocmask(SIG_SETMASK, [], strace: Process 14737 attached
NULL, 8) = 0
[pid 14737] rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
[pid 14736] rt_sigaction(SIGRT_1, {sa_handler=0x40055e, sa_mask=~[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x401820}, <unfinished ...>
[pid 14737] <... rt_sigprocmask resumed> NULL, 8) = 0
[pid 14736] <... rt_sigaction resumed> NULL, 8) = 0
[pid 14737] nanosleep({tv_sec=3, tv_nsec=0}, <unfinished ...>
[pid 14736] tkill(14737, SIGRT_1 <unfinished ...>
[pid 14737] <... nanosleep resumed> {tv_sec=2, tv_nsec=999998914}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
[pid 14736] <... tkill resumed> ) = 0
[pid 14737] --- SIGRT_1 {si_signo=SIGRT_1, si_code=SI_TKILL, si_pid=14736, si_uid=1000} ---
[pid 14736] futex(0x7fa528223f60, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid 14737] tkill(14737, SIGRT_1) = 0
[pid 14737] rt_sigreturn({mask=[RT_1]}) = -1 EINTR (Interrupted system call)
[pid 14737] rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [RT_1], 8) = 0
[pid 14737] futex(0x7fa528223f60, FUTEX_WAKE_PRIVATE, 1) = 1
[pid 14736] <... futex resumed> ) = 0
[pid 14737] exit(0 <unfinished ...>
[pid 14736] futex(0x603330, FUTEX_WAIT, 14737, NULL <unfinished ...>
[pid 14737] <... exit resumed>) = ?
[pid 14736] <... futex resumed> ) = 0
[pid 14737] +++ exited with 0 +++
[pid 14736] munmap(0x7fa528201000, 143360) = 0
[pid 14736] exit_group(0) = ?
[pid 14736] +++ exited with 0 +++
讓我困惑的是sigreturn
設置的掩碼,你可以看到它是[RT_1]
。 據我了解, sigreturn
會在被信號中斷之前恢復線程的掩碼。 但是我們可以發現sigprocmask
設置的掩碼只是一個空集。 關注以下結果:
[pid 14737] rt_sigprocmask(SIG_SETMASK, [], <unfinished ...>
[pid 14736] rt_sigaction(SIGRT_1, {sa_handler=0x40055e, sa_mask=~[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x401820}, <unfinished ...>
[pid 14737] <... rt_sigprocmask resumed> NULL, 8) = 0
[pid 14736] <... rt_sigaction resumed> NULL, 8) = 0
[pid 14737] nanosleep({tv_sec=3, tv_nsec=0}, <unfinished ...>
[pid 14736] tkill(14737, SIGRT_1 <unfinished ...>
[pid 14737] <... nanosleep resumed> {tv_sec=2, tv_nsec=999998914}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
[pid 14736] <... tkill resumed> ) = 0
[pid 14737] --- SIGRT_1 {si_signo=SIGRT_1, si_code=SI_TKILL, si_pid=14736, si_uid=1000} ---
[pid 14736] futex(0x7fa528223f60, FUTEX_WAIT_PRIVATE, 1, NULL <unfinished ...>
[pid 14737] tkill(14737, SIGRT_1) = 0
[pid 14737] rt_sigreturn({mask=[RT_1]}) = -1 EINTR (Interrupted system call)
[pid 14737] rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [RT_1], 8) = 0
換句話說,我不能理解的一件事是,掩碼最后怎么會是[RT_1]
(根據rt_sigprocmask
的第三個參數給出的結果,它代表舊的信號掩碼)? 由於一開始它被設置為空,我找不到任何其他系統調用更改掩碼。
我猜想可能是 kernel 在某個時候更改了這個掩碼,也許它會在某些情況下這樣做,例如,像 kernel 這樣的東西在線程進入信號處理程序時添加sigaction
指定的掩碼,並在sigreturn
中恢復它們。 但是相關的參考資料太難找了。
有人可以就此提供任何建議嗎? 提前致謝。
您所看到的是 pthread 庫的內部工作原理。 換句話說,不是 kernel 負責在信號掩碼中添加/刪除這些信號,而是 pthread 庫。 pthread 庫在內部使用實時信號來管理線程。 strace
將它們顯示為RT_n
。 它們被添加到掩碼中/從掩碼中移除的事實不應該讓您擔心。
在“實時信號”部分的man 7 signal
中找到有關實時信號的更多信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.