简体   繁体   中英

why SIGUSR1 kills my dd child process?

Hi I have a simple function where i create a child process and parent process.

The child process suppose to run dd if=/some/file of=/somedisk. The parent process suppose to run in a loop (until the child exists) and send signal SIGUSR1 which is forcing the dd in child process to report progress data.

Of course i have pipes where i redirect stdio and stderr from the child to the parent. (this i use in other functions and it works fine)

The problem i have is that: 1. I don't get anything on my stderr; 2. As soon as i send SIGUSR1 the process exits somehow.

    if(my_pid>0) //The parent part
            {

            close(FD_pipe_stdout[1]);// Parent process closes output side of the pipe 
            close(FD_pipe_stderr[1]);// Parent process closes output side of the pipe                               
            while(0==waitpid(my_pid, &my_pid_status, WNOHANG))
                {
                kill(my_pid, SIGUSR1); 
                sleep(1);
                //read(FD_pipe_stderr[0], pipe_error,PIPE_MAX_SIZE); // Read in a string from the stderror
                //puts(pipe_error);

                }
            puts("going out");
            read(FD_pipe_stdout[0], pipe_output,PIPE_MAX_SIZE); // Read in a string from the pipe's input side

            close(FD_pipe_stdout[0]);//on the end close the other side of pipe
            close(FD_pipe_stderr[0]);//on the end close the other side of pipe
            }         
   else
            {   // The child part
            close(FD_pipe_stdout[0]);/* Child process closes input side of the pipe */
            close(FD_pipe_stderr[0]);/* Child process closes input side of the pipe */
            dup2(FD_pipe_stdout[1],1); //redirect the stdout(1) to the fd_pipe and then close the sdtout
            dup2(FD_pipe_stderr[1],2);//redirect also stderr to the pipe
            system(dd if=/image.img of=/dev/sda);
            close(FD_pipe_stdout[1]); //on the end close the other side of pipe
            close(FD_pipe_stderr[1]); //on the end close the other side of pipe
            exit(0);
            }

I see on the screen that the parent is going out from the while loop and i don't understand why.

Thanks in advance

system() creates a child process to run the specified command, so you really have three processes here:

  1. The parent process (the one with the loop)
  2. The child process (the one that calls system()
  3. The dd process

You're signaling the child process instead of the dd process. SIGUSR1 by default causes a process to exit, so you're killing the child process.

To fix this, you could run dd using one of the exec functions, instead of calling system() :

{   // The child part
    close(FD_pipe_stdout[0]);
    close(FD_pipe_stderr[0]);
    dup2(FD_pipe_stdout[1],1);
    dup2(FD_pipe_stderr[1],2);
    execlp("dd", "dd", "if=/image.img", "of=/dev/sda", NULL);
    perror("exec failed");
    exit(1);
}

Now you only have two processes, because the child process becomes the dd process. When the parent signals the child, the signal will go to dd .

Note that there is a race condition here. The parent process may send a SIGUSR1 signal before dd starts and sets up its signal handler. To be robust, you should handle this somehow.

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