-
Notifications
You must be signed in to change notification settings - Fork 1
/
signal.c
129 lines (115 loc) · 4.47 KB
/
signal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <signal.h>
#include <string.h>
#include <errno.h>
#include "signal.h"
#ifndef __set_errno
#define __set_errno(e) errno = EINVAL
#endif /* __set_errno */
#define CHECK_ARGS(signum, handler) do { \
if (handler == SIG_ERR || signum < 1 || NSIG <= signum) { \
__set_errno(EINVAL); \
return SIG_ERR; \
} \
} while(0)
/* sig_procmask ショートカット関数 */
/* sigemptyset -> sigaddset(,signum) -> sigprocmask(how,,oldset) する */
static inline int __sig_how_procmask(int how, int signum, sigset_t *oldset) {
sigset_t newset;
if (sigemptyset(&newset) < 0) {
return -1;
}
if (sigaddset(&newset, signum) < 0) {
return -1;
}
if (sigprocmask(how, &newset, oldset) < 0) {
return -1;
}
return 0;
}
sighandler_t SYSV_signal(int signum, sighandler_t handler) {
struct sigaction newact, oldact;
CHECK_ARGS(signum, handler);
memset(&newact, 0, sizeof(newact));
memset(&oldact, 0, sizeof(newact));
newact.sa_handler = handler;
/* SYSV signal の動作を設定する */
/* a) ハンドラ起動時に処理方法がリセットされる */
/* b) ハンドラ実行中に原因となったシグナルがブロックされない */
/* c) ハンドラによって中断されたシステムコールが再開されない */
newact.sa_flags |= SA_RESETHAND;
newact.sa_flags |= SA_NODEFER;
newact.sa_flags &= ~SA_RESTART;
if (sigaction(signum, &newact, &oldact) < 0) {
return SIG_ERR;
}
return oldact.sa_handler;
}
sighandler_t SYSV_sigset(int signum, sighandler_t handler) {
struct sigaction newact, oldact;
sigset_t oldset;
CHECK_ARGS(signum, handler);
memset(&newact, 0, sizeof(newact));
memset(&oldact, 0, sizeof(newact));
if (handler == SIG_HOLD) {
/* SIG_HOLD の場合 */
/* シグナルマスクに signum を追加 */
if (__sig_how_procmask(SIG_BLOCK, signum, &oldset) < 0) {
return SIG_ERR;
}
/* signum の動作は変更しない (newact: NULL) */
if (sigaction(signum, NULL, &oldact) < 0) {
return SIG_ERR;
}
/* 呼び出し前に signum がブロックされていた場合は SIG_HOLD を返す */
/* ブロックされていない場合は変更前の handler を返す */
return sigismember(&oldset, signum) ? SIG_HOLD : oldact.sa_handler;
} else {
/* SIG_HOLD 以外の場合 */
/* signum の動作を handler (SIG_DFL, SIG_IGN 含む) にセット */
newact.sa_handler = handler;
/* SYSV signal と違い、シグナル実行中は signum がブロックされる */
if (sigaddset(&newact.sa_mask, signum) < 0) {
return SIG_ERR;
}
if (sigaction(signum, &newact, &oldact) < 0) {
return SIG_ERR;
}
/* シグナルマスクから signum を取り除く */
if (__sig_how_procmask(SIG_UNBLOCK, signum, &oldset) < 0) {
return SIG_ERR;
}
/* 呼び出し前に signum がブロックされていた場合は SIG_HOLD を返す */
/* ブロックされていない場合は変更前の handler を返す */
return sigismember(&oldset, signum) ? SIG_HOLD : oldact.sa_handler;
}
}
int SYSV_sighold(int signum) {
/* 呼び出し元プロセスのシグナルマスクに signum を追加する */
/* 成功した場合 0, 失敗した場合 1 を返す */
return __sig_how_procmask(SIG_BLOCK, signum, NULL);
}
int SYSV_sigrelse(int signum) {
/* 呼び出し元プロセスのシグナルマスクから signum を削除する */
/* 成功した場合 0, 失敗した場合 1 を返す */
return __sig_how_procmask(SIG_UNBLOCK, signum, NULL);
}
int SYSV_sigignore(int signum) {
/* signum の動作を SIG_IGN に設定する */
/* 成功した場合 0, 失敗した場合 1 を返す */
if (SYSV_signal(signum, SIG_IGN) == SIG_ERR) {
return -1;
}
return 0;
}
int SYSV_sigpause(int signum) {
sigset_t nowset;
/* signum を呼び出しプロセスのシグナルマスクから削除 */
if (SYSV_sigrelse(signum) < 0) {
return -1;
}
/* シグナルが受信されるまで、呼び出しプロセスを保留 */
if (sigprocmask(SIG_SETMASK, NULL, &nowset) < 0) {
return -1;
}
return sigsuspend(&nowset);
}