我在处理信号时遇到一些问题。我正在创建一个简单的Web服务器,但我不明白为什么我的初始进程成功捕获并处理了SIGINT
信号,但是子进程处理fork()
却似乎没有。这是我的代码:
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include "thpool.h"
#include <pthread.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/sendfile.h>
int asc;
threadpool thpool;
void sighand(int sig) { //function handler
if (sig == SIGINT) {
printf("ctr-c recived\n");
go = 0;
thpool_destroy(thpool);
shutdown(asc, 2);
close(asc);
int a = 1;
setsockopt(asc, SOL_SOCKET, SO_REUSEADDR, &a, sizeof(int));
exit(2);
}
void fun(void *client_socket) {
int sock = *(int*)client_socket;
char buffer[1024];
int n = read(sock, buffer, BUFFERSIZE);
printf("%s\n", buffer);
}
int main() {
int pid;
if (signal(SIGINT, sighand) == SIG_ERR) //signal function
perror("signal failed\n);
pid = fork();
if (pid == 0) { //new process
int port = 8666, client_socket;
struct sockaddr_in server, client;
pthread_mutex_t M;
pthread_mutex_init(&M,NULL);
int parent = getppid();
value = kill(parent, SIGTERM); //kill the parent
if (value == 0)
printf("dead parent\n");
else
perror("errore");
thpool = thpool_init(2);
//creazione socket
asc = socket(AF_INET, SOCK_STREAM, 0); //new socket
printf("\nsocket aperto\n");
bzero((char *)&server, sizeof(server));
//inizializzazione
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
bind(asc, (struct sockaddr *)&server, sizeof(struct sockaddr_in)
printf("bind effettuata\n");
listen(asc, 40)
printf("listen effettuata\n");
printf("in attesa di connessione....\n");
client_leng = sizeof(client);
while (go) {
if ((client_socket = accept(asc, (struct sockaddr *)&client, &client_leng)) < 0) {
perror("accept fallita");
exit(0);
} else {
pthread_mutex_lock(&M);
printf("accept effettuata\n");
thpool_add_work(thpool, (void *)fun, (void *)&client_socket);
puts("handler assigned\n");
pthread_mutex_unlock(&M);
}
}
}
答案 0 :(得分:1)
TL; DR :您表示的流程与您认为的不同。
您在注释中提到,您试图通过在键盘上键入CTRL-C向流程提供SIGINT
。如果您想杀死终端的前台进程组然后拥有键盘,那很好。假设您从外壳程序窗口启动程序,并且没有做任何事情使其自身进入后台,则初始进程确实将在前台进程组中,并且如果您从未fork()
,那么您所做的其他任何更改都不会直到该过程终止。因此,在该终端中键入CTRL-C将向该进程传递SIGINT
。
但是,当初始进程终止时,启动它的shell会将自己放回前台。您可以通过键入命令来检查它。此外,在初始进程成功fork()
生子的情况下,当shell将自己置于前台时,该子及其进程组将移至后台。 这时,您键入的所有CTRL-C都将进入外壳程序(忽略它),而不是Web服务器进程的子进程。
例如,您可以通过SIGINT
命令将kill
发送到在后台运行或没有控制终端的进程中
kill -INT 12345
如果您使用这种方法在SIGINT
情况下将fork
传递给子进程,您将看到该进程的已注册信号处理程序捕获并正确地处理了该信号。 / p>