C ppoll and pselect
通常 ppoll
和 pselect
會搭配 sigprocmask
使用,先透過 sigprocmask
block signal,然後在 ppoll
和 pselect
這邊再 unblock signal 做處理,例如常見的 daemon reload 可以這樣做:
// C
volatile sig_atomic_t reload_flag = 0, terminate_flag = 0;
static void sig_handler(int sig)
{
if (sig == SIGHUP) {
reload_flag = 1;
}
else if (sig == SIGTERM) {
terminate_flag = 1;
}
}
// A
sigset_t mask, orig_mask;
sigemptyset (&mask);
sigaddset (&mask, SIGTERM);
sigaddset (&mask, SIGHUP);
if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0) {
exit(EXIT_FAILURE);
}
// B
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = sig_handler;
if (sigaction(SIGHUP, &sa, NULL) == -1) {
exit(EXIT_FAILURE);
}
if (sigaction(SIGTERM, &sa, NULL) == -1) {
exit(EXIT_FAILURE);
}
// Set socket blah blah
// D
while (1) {
int poll_ret = ppoll(fds, MAX_FDS_SIZE, tv, orig_mask);
if (poll_ret == -1) {
if (errno != EINTR) {
exit(EXIT_FAILURE);
} else if (reload_flag) {
// process reload
reload_flag = 0;
} else if (terminate_flag) {
// process terminate
terminate_flag = 0;
break;
}
} else if (poll_ret > 0) {
// process socket
} else if (poll_ret == 0) {
// process timeout
} else {
exit(EXIT_FAILURE);
}
}
A
這段先將 SIGTERM
和 SIGHUP
block 起來,接著在 B
這邊設定這兩種 signal 的 callback,C
這裏的 callback function 中則去設定 flag,這裏的 sig_atomic_t
是表示這個 type 變數的操作保證是 atomic 的,通常會是 int
就是,資料的部分可以參考:
D
的部分,就是在 interrupt 進來之後,判斷這些 flag,做更進一步的處理。
至於 pselect
的部分可以參考這邊:
另外,如果要用 ppoll
的話,要先 define 一個變數,不然會出現 implicit definition
的警告:
#ifndef __USE_GNU
/* Define this to avoid a warning about implicit definition of ppoll.*/
#define __USE_GNU
#endif
#include <poll.h>
為啥不用 epoll
? 因為連線數很少,用 epoll
不見得比較好,libevent
差不多一樣道理。
Ref:
comments powered by Disqus