signal trampoline
またBSD本ネタですが、BSDの実装ではsignalが呼ばれた際にsignal contextとsignal handlerをスタック上に確保し、sigreturnで返ってくるという実装が用いられています。これをsignal trampoline codeと呼ぶそうです。
しかしgniibe先生のcodeblogを見るとどうも最近のlinuxではstruct sigactionのsa_restorerを使用するというような記述が有りますね。
restorer = &__kernel_sigreturn; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; /* Set up to return from userspace. */ err |= __put_user(restorer, &frame->pretcode); ... /* Set up registers for signal handler */ regs->esp = (unsigned long) frame;
こんな所も結構時代に沿って変わっているんですね。おもろい。これ使えばsignalが"返る"時をキャッチ出来るかなと思って、こんな感じのコードを書いてみた。
#include <stdio.h> #include <signal.h> /* from asm/i386.h */ #define SA_RESTORER 0x04000000 void sig_start(int signum) { printf("sig start\n"); } void sig_return(void) { printf("sig return\n"); sigreturn(1); /* 駄目 */ } int main(void) { struct sigaction act, old; act.sa_handler = sig_start; act.sa_restorer = sig_return; act.sa_flags = SA_RESTORER; sigaction(SIGINT, &act, &old); kill(getpid(), SIGINT); }
しかしsigreturnはuser spaceからは呼べないようになっているのか、link時にエラーが。うーん、単純にC言語の関数を指定するだけじゃ駄目なんだろうな。関数から戻る時にsigreturnを使用しないといけないのだから。Cからはこういうの指定出来なさそうだ。
飛行機の中で思い付いたネタが2本とも没...。