tags:

views:

180

answers:

1

I have a small shell that creates children (with fork()) and make them execute some commands with execvp. It support also the & option so the father can run other commands in the meanwhile. When a child die i want to write that on the console and also the child pid, so i defined a sighandler for SIGCHLD:

void backdeadchild(int sig)
{
 int pid, exitstat;
 pid = wait(&exitstat);
 printf("Child with pid: %d died", pid);
}

The problem is that after the handler prints the message also the father closes. I've managed to understand that SIGCHLD returns an EOF in stdin (and whenever father receives EOF it closes), but why SIGCHLD returns EOF? If it's normal.. how to avoid that the father closes?

A: 

If child's stdout (or any other stream) is connected to parent's stdin, it is natural that parent receives the EOF.

Alternatively parent may die from SIGPIPE (broken pipe) signal, if parent doesn't don't handle it.

qrdl
Thanks for the explanation, but so how to ignore that EOF?I tried to put a getchar() in the SIGCHLD signal handler and it seems to work, but as soon as i press enter the father closes.
Smjert
Try to catch `SIGPIPE` signal - maybe that's a reason?
qrdl
Smjert
It is almost impossible to reliably debug signals. I'd suggest to use `strace` utility on parent - it will show you all syscalls and signals caught.
qrdl
Wow, thanks i think i found the problem, but now i need some advice on how to solve it.The problem is that my SIGCHLD handler returns:rt_sigreturn(0) = -1 EINTR (Interrupted system call) in the input, after my attempt to remove the EOF with getchar() (this is why the EOF remains in input).So one solution could be to count how many child returned (increasing a global counter in the sig handler.. but it's safe?) and skip a number of EOF equal to the counter.. and if a child doesn't give a EOF i simply reset that number.
Smjert
I think global counter is ok, but it makes sense to declare it `volatile` to disallow compiler's optimiser to mess with it.
qrdl
Well, searching a bit on the internet (and since my solution seems to be still buggy) i found that there's a way to ignore the EINTR.EINTR is returned because the signal arrives when the father waits other input (so in the middle of a syscall), so if i put SA_RESTART in the flags of sigaction struct it restarts the syscall without giving EINTR.. now the only problem is that, for some reason, printf in the sighandler doesn't print anything (but i'm sure that is called and i'm sure the sigaction struct is declared on the father...) :\.
Smjert
Is possible that with SA_RESTART the printf is caching the string and it does not flush the stdout?Because if i remove SA_RESTART it works (but i need it).
Smjert