developer's diary

最近はc#のエントリが多いです

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

以上。