简体   繁体   中英

sigusr1 between parent and child in c

I want to implement an UDP server that works with three threads (over three port) that do the same thing. In one thread each there is a parent and a child: parent waiting for requests from the client, child increment a variable. When parent receive the request, it send a signal (SIGUSR1) to the pid of the child (to try, I use parentpid+1). Child by default increment the variable, by SIGUSR1 write something (for example: "I'm in sigurs1"), but actually I want also to send the status of the variable to the main thread. Howevere, this is the code:

 /** @defgroup Group4 UDP Client and Server @brief UDP/IPv4 Client and Server @{ */ /** @file UDPServer.c @author Catiuscia Melle @brief Presentazione di un UDP Echo Server IPv4. Il server, in un ciclo infinito: - riceve un messaggio - lo re-invia in echo. */ #include "Header.h" //@@@ PRIMA DI TUTTO INCLUDIAMO LA LIBRERIA PER I SEGNALI #include <signal.h> void *thread_function(void *arg); int stock = 0; //@@@ Il sigset_t viene utilizzato per rappresentare un signal set sigset_t mask; int main(){ printf("\\tIPv4 UDP Server app\\n"); int port1 = PORT, port2 = PORT2, port3 = PORT3; //INITIALITE THREAD AND VARIABLES FOR THREAD int thres; //response of the thread pthread_t a_thread, a_thread2, a_thread3; void *thread_result; //CREATE THREAD 1 thres = pthread_create(&a_thread, NULL, thread_function, &port1); if (thres != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } //CREATE THREAD 2 thres = pthread_create(&a_thread2, NULL, thread_function, &port2); if (thres != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } //CREATE THREAD 3 thres = pthread_create(&a_thread3, NULL, thread_function, &port3); if (thres != 0) { perror("Thread creation failed"); exit(EXIT_FAILURE); } thres = pthread_join(a_thread, &thread_result); if (thres != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); } thres = pthread_join(a_thread2, &thread_result); if (thres != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); } thres = pthread_join(a_thread3, &thread_result); if (thres != 0) { perror("Thread join failed"); exit(EXIT_FAILURE); } return 0; } void *thread_function(void *arg) { pid_t pid; int parentpid = getpid(); printf("Il pid della thread vale %d\\n",parentpid); int port = *((int *) arg); //@@@ Nella variabile signo salverò il numero di segnale che mi restituisce la wait int err, signo; printf("Porta %d\\n",port); printf("ENTER TO THREAD\\n"); int res = 0; //valore di ritorno delle APIs /* socket: servirà per la comunicazione col server */ int sockfd = 0; /* open socket di tipo datagram */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket error: "); return FAILURE; } /* indirizzo IPv4 del server, senza hostname resolution */ struct sockaddr_in server; socklen_t len = sizeof(server); memset(&server, 0, sizeof(server)); //azzero la struttura dati server.sin_family = AF_INET; //specifico l'Address Family IPv4 /* Specifico l'indirizzo del server: qualsiasi interfaccia */ server.sin_addr.s_addr = htonl(INADDR_ANY); /* Specifico la well-known port */ server.sin_port = htons(port); //setto l'indirizzo well-known del socket res = bind(sockfd, (struct sockaddr *)&server, len); if (res == -1) { perror("Bind error: "); close(sockfd); exit(1); }//fi ssize_t n = 0; char buffer[BUFSIZE]; struct sockaddr_in client; char address[INET_ADDRSTRLEN] = ""; int quit = 0; if ((pid = fork()) < 0) { printf("Fork error<n"); } else if (pid == 0) { /* child */ printf("child dal pid %d\\n",getpid()); while(1){ //@@@ La sigwait non fa che attendere l'arrivo di un segnale err = sigwait(&mask, &signo); //@@@ Una volta terminata la sigwait, ossia quando ha ricevuto un segnale //(se no è successo un errore), possiamo switchare il segnale arrivato, che //è salvato in signo switch (signo) { //@@@ Ora gestisco, se gli ho mandato un SIGUSR1, ossia un flag che, arrivato //a destinazione indica di eseguire quel segnale che il processo che lo riceve //lo implementa come vuole. Si sa che si deve eseguire quel segnale, di libera //interpretazione case SIGUSR1: printf("Sigusr1\\n"); printf("Stock vale %d\\n",stock); break; //@@@ In caso gli mandassi SIGINT, valuta sempre se ci sono errori e poi esci case SIGINT: printf("Sigint\\n"); //@@@ Di default comunque, controlla se ci sono errori e poi esci default: stock++; printf("Sto producendo %d dalla porta %d\\n",stock, port); sleep(2); } } } else { printf("parent dal pid %d\\n",getpid()); /* parent */ while (!quit) { printf("Main thread entrato nel ciclo\\n"); n = recvfrom(sockfd, buffer, BUFSIZE-1, 0, (struct sockaddr *)&client, &len); printf("Mando segnali"); //@@@ Inizializza il segnale settato set a escludere tutti i segnali definiti sigemptyset(&mask); //@@@ Aggiunge il segnale signum al segnale settato set. Con sigaddset modifichiamo //set, ma non blocchiamo o sblocchiamo alcun segnale! //Mettiamoli quindi SIGURS1 sigaddset(&mask, SIGUSR1); //@@@ E anche SIGINT sigaddset(&mask, SIGINT); //@@@ pthread_sigmask esamina e cambia segnali bloccati. Con SIG_BLOCK il set //risultante è l'unione del set corrente e il set di segnale indicato da set if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) { fprintf(stderr, "thread mask failed\\n"); exit(EXIT_FAILURE); } kill(parentpid+1,SIGUSR1); printf("Segnale inviato al pid %d\\n",(parentpid+1)); if (n == -1) { perror("recvfrom() error: "); continue; // close(sockfd); // return FAILURE; } }//wend printf("Stockmann %d\\n",stock); //qui non ci arrivo mai... close(sockfd); } return NULL; } /** @} */ 

this is Header.h (but it's not necessary to see it)

 /** @addtogroup Group11 @{ */ /** @file Header.h @author Catiuscia Melle @brief Header comune al client e server dell'esempio L'header definisce costanti comuni al client e server. */ #ifndef __HEADER_H__ #define __HEADER_H__ #include <stdio.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <signal.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> //resolver related functions #include <sys/types.h> //necessario su Mac #include <stdlib.h> #include <ctype.h> //toupper() #include <stdbool.h> //THIS FOR RAND FUNCTION #include <stdlib.h> #include <time.h> //THIS FOR THREADS #include <pthread.h> #define PORTNUMBER 49152 /**< UDP listening port, decimal */ #define PORT 49152 /**< UDP listening port, decimal */ #define PORT2 49153 /**< UDP listening port, decimal */ #define PORT3 49154 /**< UDP listening port, decimal */ #define SERVICEPORT "49152" /**< UDP listening port, name */ #define PORT_STRLEN 6 /**< lunghezza di una stringa rappresentativa di un indirizzo di trasporto */ #define BACKLOG 10 /**< dimensione della coda di connessioni */ #define SIZE 15 /**< dimensione della coda di connessioni concorrenti gestite dal server */ #define BUFSIZE 512 /**< dimensione del buffer di messaggio */ #define FAILURE 3 /**< definizione del valore di errore di ritorno del processo in caso di errori delle Sockets API */ #define INVALID 5 /**< se i due processi non sono avviati col giusto numero di parametri */ #define ERROR 1 /**< valore di errore */ #define INSUCCESS -1 /**< valore di ritorno non valido */ #define SEMAPHORE_NAME "gbrunetta317" #endif /* __HEADER_H__ */ /** @} */ 

The problem is that when I send something with the client, the value inside case: Sigurs1 doesn't appear:

问题

Actually, it doesn't returns nothing from the SIGUSR1 defined in child, but you can see that it stop that process (in fact you can see that it doesn't work again with port 49512, because pidparent+1 is associated with that port). I hope I was clear. How I can solve it?

I discovered that it fail with shmat.. I don't know why, but I rewrite the code according with this example: How to trigger SIGUSR1 and SIGUSR2? And now it works fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM