- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个循环处理 accept(2)
调用。我希望能够在将 SIGINT
发送到程序时执行一些清理操作。我的第一个想法是使用 signal
函数。
void signal_handler(int signal) {
printf("Caught signal\n");
}
int main() {
signal(SIGINT, &signal_handler);
// ...
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
// ...
}
但是,这只是打印“捕获信号”,然后程序继续。
如果我修改 main
以使用 sigaction
,程序将按预期工作。
int main() {
struct sigaction sa;
sa.sa_handler = &signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
// ...
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
// ...
}
发送 SIGINT 后,我收到捕获信号
,然后收到接受:中断的系统调用
。来自 accept(2)
ERRORS
...
EINTR The system call was interrupted by a signal that was caught before a valid connection arrived; see signal(7).
我知道 sigaction
更现代,我应该使用它而不是 signal
,但我很好奇为什么它提供了这种功能差异。
下面我为每种情况提供了一个完整的可用示例程序。
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFFER_SIZE 32
void signal_handler(int signal) {
printf("Caught signal\n");
}
int main() {
signal(SIGINT, &signal_handler);
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *addr_info;
int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
if (info_result != 0) {
printf("Getting address failed\n");
return 1;
}
int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
if (sock == -1) {
printf("Socket Failed\n");
return 1;
}
int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
if (bind_result == -1) {
close(sock);
printf("Bind Failed\n");
return 1;
}
int listen_result = listen(sock, 8);
if (listen_result == -1) {
close(sock);
printf("Listen Failed\n");
return 1;
}
printf("Waiting...\n");
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
printf("Got fd %d\n", accept_fd);
char *buffer = malloc(BUFFER_SIZE * sizeof(char));
int n;
while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
printf("%.*s\n", n, buffer);
}
close(sock);
}
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFFER_SIZE 32
void signal_handler(int signal) {
printf("Caught signal\n");
}
int main() {
struct sigaction sa;
sa.sa_handler = &signal_handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
struct addrinfo *addr_info;
int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
if (info_result != 0) {
printf("Getting address failed\n");
return 1;
}
int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
if (sock == -1) {
printf("Socket Failed\n");
return 1;
}
int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
if (bind_result == -1) {
close(sock);
printf("Bind Failed\n");
return 1;
}
int listen_result = listen(sock, 8);
if (listen_result == -1) {
close(sock);
printf("Listen Failed\n");
return 1;
}
printf("Waiting...\n");
int accept_fd = accept(sock, NULL, NULL);
if (accept_fd == -1) {
close(sock);
perror("accept");
return 1;
}
printf("Got fd %d\n", accept_fd);
char *buffer = malloc(BUFFER_SIZE * sizeof(char));
int n;
while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
printf("%.*s\n", n, buffer);
}
close(sock);
}
最佳答案
在 BSD 和 Linux 上,signal()
相当于将 sa_flags
设置为 SA_RESTART
的 sigaction()
。如果您在 sigaction()
代码中设置该标志,它将与您的 signal()
代码表现相同。如果这不是您想要的,那么您只能使用 sigaction()
。
来自 Linux man page 的注释(也适用于 BSD 和 OS X):
On BSD, when a signal handler is invoked, the signal disposition is not reset, and further instances of the signal are blocked from being delivered while the handler is executing. Furthermore, certain blocking system calls are automatically restarted if interrupted by a signal handler (see signal(7)). The BSD semantics are equivalent to calling sigaction(2) with the following flags:
sa.sa_flags = SA_RESTART;
关于c - sigaction 将 SIGINT 传递给系统调用,但不传递信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52231219/
我在一些代码中看到以下用法: struct sigaction term_handler; // global variable without initialization ... sigacti
我正在做简单的 sigaction 示例来练习 C,但是当我尝试编译代码时,它声称 struct sigaction 不存在 [1]。 当我检查我生成的一些旧代码时,我发现我在文件的最顶部添加了一些
如果我们使用 sigaction 来定义一个信号处理程序,那为什么我们不需要重置处理程序呢?如果我们使用 signal(sig_no,handler_func)那么我们必须重置它。为什么是这样? #i
我正在学习信号并编写了一个简单的程序来处理它们。 所以我输入一个数字,然后使用 fork 创建一个进程。父进程应该将数字作为信号发送给子进程,然后 child_signal 处理程序应该将数字的平方作
我在 C++ 中对此类使用 sigaction 时遇到问题: class SerialHandler{ private: ... /* Action Handling
我有以下 sigaction 处理程序代码 void signal_term_handler(int sig) { int rc = async_lockf(pid_file, F_UNLCK
我正在使用 sigaction 作为信号,我正在为此使用一个简单的结构。我实际上是从手册页中获取的。有人可以向我解释结构中的第二行是做什么的吗?还有一个错误: error: expected decl
有没有办法用sigaction结构和函数只捕获一次信号?更具体地说,我想简单地重置为默认特定信号 (SIGINT)。是否有可能在处理程序中实现这一点? 编辑 所以,这样的事情是正确的: void si
我正在将程序的信号处理从 signal() 转换为 sigaction()。 根据UNIX spec struct sigaction 应该至少有 4 个成员; sa_handler、sa_mask、
我很难理解 sigaction() 的方式有效。 在 , sigaction 定义为 int sigaction(int sig, const struct sigaction *act, struc
我正在查看 sigaction 的手册页,最后我看到了以下行。 sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
在我下面的代码中,如果我将 old_act 声明为全局变量,那么程序可以正常工作。如果在 main 中声明: 如果使用 SA_RESTART,它工作正常 如果不使用 SA_RESTART,则会导致段错
我必须向进程发送两个信号,SIGUSR1 和 SIGUSR2,以便修改程序中的特定 bool 变量 (SIGUSR1 将其设置为 true,SIGUSR2 将其设置为 false)。所以我写了一个 s
我正要向我们这里的应用程序添加一个额外的信号处理程序,我注意到作者使用了 sigaction() 来设置其他信号处理程序。我打算使用 signal()。按照惯例,我应该使用 sigaction(),但
编译以下代码, struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = &handler; sigaction (SIGR
我有一个程序,它为 SIGSEGV 安装信号处理程序。在信号处理程序中(我 try catch 崩溃)我重新启动我的应用程序。 但是当我的应用程序复活时,它不再处理 SIGSEGV。 这是一个例子:
我注意到 sigaction 被定义为结构和函数(http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html):
每次收到 SIGINT 时,我都使用 sigaction() 执行操作。我见过的所有教程都使用这个原型(prototype)作为信号处理程序 void sig_handler(int sig); 有没
这个问题在这里已经有了答案: What is it with printf() sending output to buffer? (3 个答案) 关闭 3 年前。 我是 Unix 中信号的新手,这
我正在尝试以下信号处理程序,引用在线教程,但它似乎不起作用,我的代码有什么问题: #include #include #include #include #include typedef void (
我是一名优秀的程序员,十分优秀!