1

on receiving a SIGUSR1 signal, I want to display the value read by the child from the pipe.

Having a little issue. It is always displaying 0 despite getppid() was written to pipe by parent process. Any solution? `

#include <stdio.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> char bufP[10], bufC[10]; int gpid; void handler(int signum){ signal(SIGUSR1, handler); if (signum == SIGUSR1){ printf("SIGUSR1 received\n"); gpid = atoi(bufC); printf("Grandparent: %d\n", gpid); exit(0); } } int main(void){ int pid, fd[2]; pipe(fd); pid = fork(); signal(SIGUSR1, handler); if (pid == 0){ //child close(fd[1]); read(fd[0], bufC, sizeof(bufC)); close(fd[0]); }else{ //parent close(fd[0]); sprintf(bufP, "%d", getppid()); write(fd[1], bufP, sizeof(bufP)); kill(pid, SIGUSR1); close(fd[1]); } } 

`

Thanks for your response.

1
  • Never use printf inside a signal handler. It's not async signal safe Commented Mar 9, 2015 at 14:30

2 Answers 2

1

You seem to assume that the signal will always be handled after the read() has completed, which is not the case. Signals are asynchronous by nature and can arrive anytime (even halfway through the read()!). Basically you are building your program upon a so-called race condition, which you should really avoid.

Sign up to request clarification or add additional context in comments.

4 Comments

There is a 2nd race introduced by setting the signal handler after forking off the child.
Also the child could already have ended before any writes had been performed, or the signal had been sent, or delivered.
@alk: Sure there is, and I don't see even why the OP is also setting the signal handler up in the parent as well. But I don't see how the child could end before the write() has been performed, since it will be blocked on the read() call until data is available. Still, it might end before the signal is sent, I agree on this.
Correct, the read() blocks the child. So the child defintily won't end before the parent's write ended. My bad.
0

While there certainly is a race condition here, it's not what causing trouble. The problem is that your signal is triggered while the read() call in the child process is blocked. You can add a sufficiently long pause in the parent process to let child's read() complete:

if (pid == 0){ //child close(fd[1]); read(fd[0], bufC, sizeof(bufC)); close(fd[0]); sleep(10); // wait for the signal to arrive }else{ //parent close(fd[0]); sprintf(bufP, "%d", getppid()); write(fd[1], bufP, sizeof(bufP)); close(fd[1]); // close right away to be sure the buffers are flushed sleep(1); // make sure the child has finished reading the buffer kill(pid, SIGUSR1); } 

Of course, remarks about race conditions and the fact that you should avoid them are still true. This code is not "production quality", it will fail if the load on your system is so heavy that 1 second is not enough to schedule the child process and finish that read() call.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.