How can I print a message from a signal handler - linux

I have small project for practice in system calls. The idea is to create a Rock paper scissors game. The controller need to create two child processes and when two processes are created they are supposed to send ready command to the controller (parent process) using SIGUSR1 signal. I have created the two children processes and the signal sent the signal to the controller but the problem message does not print out. what am I wrong?
Here is my code.
#include<stdio.h>
#include<unistd.h> // fork(); for creating processes and pipe()s
#include<signal.h>
#include<sys/signal.h>
#include<stdlib.h>
void handle_sigusr1(int sig){
printf("Sending ready command...\n");
}
int x = 0;
int main(int args, char* argv[]){
int player0, player1;
player0 = fork();
if(player0 != 0){
player1 = fork();
}
if( player0 == 0){
kill(getppid(), SIGUSR1);
sleep(2);
}else if(player1 == 0){
sleep(3);
kill(getppid(), SIGUSR1);
}else{
wait(NULL);
struct sigaction sa = { 0 };
sa.sa_flags = SA_RESTART;
sa.sa_handler = &handle_sigusr1;
sigaction(SIGUSR1, &sa, NULL);
if(signal(SIGUSR1, handle_sigusr1)){
x++;
printf("Controller: Received ready command. Total %d\n", x);
}
}
return 0;
}

In your code, there are 2 major issues to modify.
First of all, move the signal handler above the wait() function, otherwise you are defining how to handle the signal after receiving it
signal(SIGUSR1, handle_sigusr1);
wait();
Then, the parent process is waiting for only 1 child to receive the signal. You should add a loop to wait both the child processes in the parent statement branch

Related

how to stop a thread that worked in infinity loop from another thread linux(c language)?

in main, I create two threads
thread 1 for the first func
thread 2 for second func2 (it included while(1))
i try to stop func2 from func by using pthread_cancel()
but didn't work and after I finish with func the Linux return to func2 and continue the infinite loop
is there a way to stop a thread that worked with an infinite loop from another thread ????
I think you need pthread_exit();
#include <pthread.h>
void pthread_exit(void *rval_ptr);
So we see that this function accepts only one argument, which is the return from the thread that calls this function. This return value is accessed by the parent thread which is waiting for this thread to terminate. The return value of the thread terminated by pthread_exit() function is accessible in the second argument of the pthread_join which just explained above.
You can see this example below:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
pthread_t tid[2];
int ret1,ret2;
void* doSomeThing(void *arg)
{
unsigned long i = 0;
pthread_t id = pthread_self();
for(i=0; i<(0xFFFFFFFF);i++);
if(pthread_equal(id,tid[0]))
{
printf("\n First thread processing done\n");
ret1 = 100;
pthread_exit(&ret1);
}
else
{
printf("\n Second thread processing done\n");
ret2 = 200;
pthread_exit(&ret2);
}
return NULL;
}
int main(void)
{
int i = 0;
int err;
int *ptr[2];
while(i < 2)
{
err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
if (err != 0)
printf("\ncan't create thread :[%s]", strerror(err));
else
printf("\n Thread created successfully\n");
i++;
}
pthread_join(tid[0], (void**)&(ptr[0]));
pthread_join(tid[1], (void**)&(ptr[1]));
printf("\n return value from first thread is [%d]\n", *ptr[0]);
printf("\n return value from second thread is [%d]\n", *ptr[1]);
return 0;
}

How to propagate signal in C from parent to child which are in own process group?

Suppose I have 10 child processes which are moved to their own process group by setpgid(0,0) just before the exec. (Each child also has children which are also in their own process group.)
My foreground process gets ctrl-c SIGINT signal and I want to propagate it to the all child processes (all children are in different group). How to do that?
hope that quick draft better explain my problem.
void handler(int signal) {
// resend SIGINT to all childs but childs are in different pgid
}
int main(int argc, char* argv[]){
struct sigaction sa;
sa.sa_handler = &handler;
sigaction(SIGINT, &sa, NULL);
pid_t pid[SIZE];
int i = 0;
// if argv is ge 2;
for (;i < SIZE; i++) // SIZE is number of the elements in argv
{
pid[i] = fork();
if(pid[i] == 0)
{
setpgid(0,0);
// execv self here but with one less element in argv;
}
}
while(1){}; // infinity loop (waits for ctrl-c from foreground process)
// prints to the terminal pid and pgid
// waits here for all childs to finish and then close self
}
What about forwarding the signal in the signal handler of main process, manually. Maybe you can provide some code snippet to clarify the situation you're in.
void signalHandler(int signum)
{
kill(child_pid,signum);
//other stuff
}

Proper way of handling SIGCHLD, EINT, and accept() in Linux

I have a program that creates a TCP server. When the accept() connects to a client, I fork() it and handle the connection. When that client leaves it calls the waitpid() because of the SIGCHLD, but this causes a EINTR in the accept(). My question is how should this be handled? I've read so many different ways.
Most say to ignore it the EINT and try the accept() again. I've even seen a macro to do just that: TEMP_FAILURE_RETRY(). Some say to set the sigaction flags SA_RESTART and SA_NOCLDSTOP. I've tried that and it introduces other errors (errno = ECHILD). Also, how should the child exit? I've seen both _exit(0) and exit(0).
int main( int argc, char *argv[] )
{
int sockfd, newsockfd, clilen;
struct sockaddr_in cli_addr;
int pid;
f_SigHandler();
sockfd = f_SetupTCPSocket();
clilen = sizeof(cli_addr);
while (1)
{
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
{
if( errno == EINTR ) continue;
else exit(1) ;
}
pid = fork();
if (pid == 0)
{
close(sockfd);
doprocessing();
close(newsockfd);
_exit(0);
}
else
{
close(newsockfd);
}
}
}
The SIGCHLD handling is:
void f_ChildHandler(int signal_number)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
{
}
}
void f_SigHandler(void)
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = f_ChildHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGCHLD, &sa, NULL);
}
In your case, a plain SA_RESTART and the waitpid() in the handler probably suffices. When exit code is uninteresting, you can pass SA_NOCLDWAIT additionally.
When client exit must be handled in a more complex way, you can catch EINTR in the main program and call waitpid() there. To make it race free, you should use pselect() to block the signal. Alternatively, you can create a signalfd and use it in select/poll with your sockfd.
Child should use _exit() to prevent execution of atexit() handlers (e.g. which write termination entries into a file).

second call prctl() dont work

I try write program, which realize next idea:
After start, program using fork() and:
parent process stopped on function wait() (for waiting death child process);
child process use prctl(PR_SET_PDEATHSIG, SIGHUP), and setup signal handler (It's helps detect parent death);
After death any process, program use fork() again.
void forking_process() {
pid_t id;
printf("forking_process is called!\n");
if (id = fork()) {
parent_process_operation();
} else {
child_process_operation();
}
}
void parent_process_operation() {
int status = 0;
printf("It's parent process! Pid = %d\n", (int)getpid());
pid_t chid = wait(&status);
printf("Terminated child process with PID = %d\n", chid);
inform_about_parent_death(status);
}
void child_process_operation() {
printf("It's child process! pid = %d, ppid = %d\n",
(int)getpid(), (int)getppid());
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = inform_about_parent_death;
if (sigaction(SIGHUP, &sa, NULL))
fprintf(stderr, "sigaction error\n");
prctl(PR_SET_PDEATHSIG, SIGHUP);
while(1) {
printf("."); fflush(stdout);
sleep(1);
}
}
void inform_about_parent_death(int i) {
printf("Process is dead. Restart!\n");
forking_process();
}
int main (void) {
forking_process();
return EXIT_SUCCESS;
}
If I run this application, and in another terminal kill child process - then will create child process.
If I kill the parent process once, - signal handler started and call fork().
If I again kill the parent process, - signal handler not responded.
That is - prctl() in first process work, but prctl() in second child process don't work.
Why it is happen? How I can correct it's program?

System V IPC msgrcv with timer Howto

We are using a System V message queue with the msgrcv function being called in blocking mode. We want to implement a timer on the blocking msgrcv function so that when the timer expires and we have not received a message, we can unblock msgrcv and continue execution.
Do you have any suggestions on how we can achive this by programming?
I have solved this problem using alarm signal.
Please check the following program if it helps:
int msg_recv(int id, MSG_DATA *msgptr)
{
int n;
**alarm(2);** //After 2 second msg_recv interrupt and return errno "Interrupted system call"
n = msgrcv(id, (MSG_DATA *) msgptr, sizeof(MSG_DATA) , 0, 0);
perror("Return from msgrcv");
printf ("N = %d\n %d %s\n\n",n,errno,strerror(errno));
if ( n < 0) //goto LOOP; // This forces the interrupted msgrcv to repeat
return(n);
}
void sigalrm_handler()
{
printf("Alarm signal delivered !\n");
return;
}
int main();
int main()
{
//signal (SIGALRM, times_up); /* go to the times_up function */
/* when the alarm goes off. */
**signal(SIGALRM, sigalrm_handler);**
int msqid; /* return value from msgget() */
MSG_DATA msg_data;
msqid = 0;
printf("Ready to receive ... \n");
**msg_recv(msqid, &msg_data);**
printf("read message \n");
return 0;
}
signal handler has a int param:
void sigalrm_handler(int)
{
printf("Alarm signal delivered !\n");
return;
}

Resources