Reputation: 3
I have some problem with processing signals. I'm creating a simple web server, and I don't understand why my initial process successfully catches and handles SIGINT
signals, but the child processes it fork()
s seem not to do so. Here is my code:
#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);
}
}
}
Upvotes: 0
Views: 738
Reputation: 181714
TL;DR: you are signaling a different process than you think you are.
You mention in comments that you are trying to deliver a SIGINT
to your process by typing CTRL-C on the keyboard. That's fine when you want to kill the foreground process group of the terminal then owning the keyboard. Supposing that you launch your program from a shell window and it does nothing to put itself in the background, the initial process will indeed be in the foreground process group, and if you never fork()
then nothing else you do do changes that until the process terminates. Typing CTRL-C in that terminal will therefore deliver a SIGINT
to that process.
HOWEVER, when the initial process dies, the shell that launched it puts itself back in the foreground. You can check this by typing commands to it. Moreover, in the case where the initial process successfully fork()
s a child, the child and its process group move into the background when the when the shell puts itself in the foreground. At that point, any CTRL-C you type goes to the shell (which ignores it), not to the child of your webserver process.
You can send a SIGINT
to a process running in the background or without a controlling terminal via the kill
command, for example
kill -INT 12345
If you use that method to deliver a SIGINT
to the child process in your fork
ing case, you will see that the process's registered signal handler catches and handles the signal exactly as it should.
Upvotes: 1