Signal from parent to its child processes in Linux

Viewed 63

I will write shortly what i want to do with my code and what's the real output. I have a parent process which creates two child processes. Each of the two process read 100 bytes from a different file, child 1 read from "child1.txt", child 2 read from "child2.txt". I want to force to execute child 2 before child 1 through the use of signals.

I created the two child process and paused them (pause end when they receive a signal). So I sent a signal to the child 2, then i sent a signal to the child 1. In this way I expect they will do what i want but they don't (it shows always child1.txt content)and i do not understand why.

This is the code

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <wait.h>

void my_handler(int signo);

int main(int argc, char *argv[]){
    signal(SIGCHLD,my_handler);
    pid_t pid[2]; //here is where I save child pid
    char buffer[100];
    for (int i=0;i<2;i++){
        if((pid[i]=fork())==0){
            signal(SIGUSR1,my_handler);
            int fd,nbyte;
            pause();
            if(i==0){
                fd=open("Child1.txt",O_RDONLY);
            }else{
                fd=open("Child2.txt",O_RDONLY);
            }
            nbyte=read(fd,buffer,100);
            buffer[nbyte-1]='\0';
            write(STDOUT_FILENO,buffer,strlen(buffer));
            exit(1);
        }
        sprintf(buffer,"Child %d\n",(int)pid[i]);
        write(STDOUT_FILENO,buffer,strlen(buffer));
    }
    kill(pid[1],SIGUSR1); //I send a signal to unpause child2
    wait(NULL); // wait child 2 to terminate
    kill(pid[0],SIGUSR1); //unpause child 1
    wait(NULL); // wait child 1 to terminate

}


void my_handler(int signo){
}
1 Answers

the following proposed code::

  1. cleanly compiles
  2. performs the desired functionality
  3. properly checks for errors
  4. uses proper variable typing
  5. eliminates the 'magic' numbers by giving them meaningful names

and now the proposed code:

#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <wait.h>


#define BUF_SIZE     100
#define NUM_CHILDREN 2


void my_handler(int signo);

int main( void )
{
    //signal(SIGCHLD,my_handler);
    pid_t pid[ NUM_CHILDREN ] = {0};
    char buffer[ BUF_SIZE +1];

    for ( int i=0; i<NUM_CHILDREN; i++ )
    {
        if((pid[i]=fork())==0)
        { // then child
            signal(SIGUSR1,my_handler);
            int fd;
            ssize_t nbyte;
            pause();

            if(i==0)
            {
                if( (fd=open("child1.txt",O_RDONLY) ) == -1 )
                {
                    perror( "open to read child1.txt failed" );
                    exit( EXIT_FAILURE );
                }
            }

            else
            {
                if( (fd=open("child2.txt",O_RDONLY) ) == -1 )
                {
                    perror( "open to read child2.txt failed" );
                    exit( EXIT_FAILURE );
                }
            }

            if( (nbyte=read(fd,buffer,100) ) ==-1 || nbyte == 0 )
            {
                perror( "read failed" );
                exit( EXIT_FAILURE );
            }

            buffer[nbyte]='\0';

            write(STDOUT_FILENO,buffer,strlen(buffer));
            fflush( stdout );
            close( fd ); 

            exit( EXIT_SUCCESS );
        }

        else if( pid[i] > 0 )
        { // then parent 
            sprintf( buffer,"Child %d PID %d\n", i, (int)pid[i] );
            write( STDOUT_FILENO, buffer, strlen(buffer) );
            fflush( stdout );
        }

        else
        { // fork failed
            perror( "fork failed" );
        }
    }

    sleep(1);  // allow all child processes to be ready for signal

    if( pid[0] > 0 )
    {
        kill(pid[0],SIGUSR1); //send a signal to unpause child 0
        wait( NULL ); 
    }

    if( pid[1] >  0 )
    {
        kill(pid[1],SIGUSR1); //unpause child 1
        wait( NULL ); 
    }
}


void my_handler(int signo)
{
    (void)signo;
}

contents of child1.txt (note I used all lower case for the file name)

123

contents of child2.txt (note I used all lower case for the file name)

456

a run of the code results in:

Child 0 6630
Child 1 6631
123

456
Related