signal(2) signal(SIGINT, sig_handler);を試した。
とりあえずsignalのman結果。
SIGNAL(2) Linux Programmer’s Manual SIGNAL(2) 名前 signal - ANSI C シグナル操作 書式 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t sighandler); 説明 signal() システム・コールは signum で指定された番号のシグナルに新しいシグ ナル・ハンドラーを設定する。このシグナル・ハンドラーは sighandler に設定さ れ る。 sighandler は、ユーザーの指定した関数、 SIG_IGN、 SIG_DFL のいずれ かである。 シグナル番号 signum のシグナルを受けると次のように動作する。対応するハンド ラ ーが SIG_IGN に設定されている場合は、シグナルは無視される。ハンドラーが SIG_DFL に設定されている場合は、シグナルに関連づけられたデフォルトの動作を 行 う (signal(7) を参照)。ハンドラーが関数 sighandler に設定されている場合 は、まず最初にハンドラーが SIG_DFL にリセットされ (あるいは実装に依存す る シ グナルのブロックが実行され)、次に signum を引き数として sighandler が呼 ばれる。 シグナルに対してシグナルハンドラー関数を使うことは、「シグナルのキャッチ」 と呼ばれる。シグナル SIGKILL と SIGSTOP はキャッチできず、無視することもで きない。 返り値 signal() 関数は今までのシグナル・ハンドラーの値を返すか、エラーの 場 合 は SIG_ERR を返す。 移植性 Unix のオリジナルの signal() はハンドラーを SIG_DFL にリセットする。 Sys- tem V (と Linux カーネルと libc4,5) も同じである。一方、BSD ではハンドラー のリセットを行わず、ハンドラーが呼ばれている間にシグナルの新しいインスタン スが発生するのをブロックする。 glibc2 ライブラリでは BSD の動作に従って い る。 libc5 システムにおいて <signal.h> のかわりに <bsd/signal.h> をインクルード すると、 signal() は __bsd_signal に再定義されて BSD 方式となる。これは 推 奨されない。 glibc2 システムにおいて _XOPEN_SOURCE のような機能検査マクロを定義したり、 この関数とは別の sysv_signal 関数を使ったりすれば、以前のような動作をす る 。これは推奨されない。 マクロの定義やファイルのインクルードでこの関数の方式を変更しようとするのは 、良くない考え方である。 signal() を使うのを完全に避けて、代わりに sigac- tion(2) を使った方が良い。 注意 マルチスレッドプロセスにおけるこの関数の結果は、指定されていない。 他 の場所での処理が任意の箇所で割り込まれるため、ルーチン handler は非常に 注意しなければならない。 POSIX には「安全な関数」という概念がある。シグ ナ ル が安全でない関数に割り込み、かつ handler がその安全でない関数を呼び出し ていた場合、その挙動は未定義である。安全な関数は様々な規格に明確にリストさ れている。 POSIX.1-2003 でのリストは以下の通りである: _Exit() _exit() abort() accept() access() aio_error() aio_return() aio_suspend() alarm() bind() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect() creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdata- sync() fork() fpathconf() fstat() fsync() ftruncate() getegid() geteuid() getgid() getgroups() getpeername() getpgrp() getpid() getppid() getsock- name() getsockopt() getuid() kill() link() listen() lseek() lstat() mkdir() mkfifo() open() pathconf() pause() pipe() poll() posix_trace_event() pselect() raise() read() readlink() recv() recvfrom() recvmsg() rename() rmdir() select() sem_post() send() sendmsg() sendto() setgid() setpgid() setsid() setsockopt() setuid() shutdown() sigaction() sigaddset() sigdelset() sigemptyset() sigfillset() sigismember() signal() sigpause() sigpending() sigprocmask() sigqueue() sigset() sigsuspend() sleep() socket() socketpair() stat() symlink() sysconf() tcdrain() tcflow() tcflush() tcgetattr() cgetpgrp() tcsendbreak() tcsetattr() tcsetpgrp() time() timer_getoverrun() timer_gettime() timer_settime() times() umask() uname() unlink() utime() wait() waitpid() write(). POSIX に よると、 kill(2) や raise(3) 関数で生成できない SIGFPE, SIGILL, SIGSEGV シグナルを無視した後の動作は未定義である。 0 による整数割り算の 結 果は未定義となる。ある種のアーキテクチャーでは、これは SIGFPE シグナルを生 成する。 (同様に負の最大整数を -1 で割ると SIGFPE が生成されるかもしれない 。) このシグナルを無視すると無限ループに陥るかもしれない。 SIGCHLD の動作として SIG_IGN を設定した場合の詳細な動作については、 sigac- tion(2) を参照すること。 sighandler_t の使用は GNU 拡張である。各種バージョンの libc でこの型は定義 済 みである; libc4 と libc5 では SignalHandler を定義している。 glibc では sig_t を定義しており、 _GNU_SOURCE が定義されている場合に は sighandler_t も定義されている。 準拠 C89, POSIX.1-2001. 関連項目 kill(1), alarm(2), kill(2), pause(2), sigaction(2), sigpending(2), sig- procmask(2), sigqueue(2), sigsuspend(2), killpg(3), raise(3), sigse- tops(3), sigvec(3), feature_test_macros(7), signal(7) Linux 2.2 2000-04-28 SIGNAL(2)
試した。
signal_sigint_sample.c
#include <stdlib.h> #include <signal.h> #include <unistd.h> static void sig_handler(const int sig) { printf("SIGINT handled.\n"); exit(EXIT_SUCCESS); } int main (int argc, char **argv) { signal(SIGINT, sig_handler); sleep(60); }
コンパイルして動かす。
[root@localhost c]#gcc signal_sigint_sample.c [root@localhost c]# ./a.out(実行して[Ctrl]+Cを押さずに終了するまで待つ) [root@localhost c]# echo $? 0 [root@localhost c]# ./a.out(実行して[Ctrl]+Cを押す) SIGINT handled. [root@localhost c]# echo $? 0
exit(EXIT_SUCCESS);をコメントアウトしてみた。
[root@localhost c]# ./a.out SIGINT handled. [root@localhost c]# echo $? 59
exit(EXIT_FAILURE)にしてみた。
[root@localhost c]# gcc signal_sigint_sample.c [root@localhost c]# ./a.out SIGINT handled. [root@localhost c]# echo $? 1
以上。