1

Here is an example piece of my code

signal(SIGCHLD, SIG_IGN);

ret = system("ls -al");

if(ret < 0)
{
    perror("system failed");
    printf("return value is %d\n", ret);
}

The ls -al command can be executed without any problem.

But the return value of system() is always -1. In this case, I can't get the real return value of the command.

Some reference says that ignore SIGCHLD would affect waitpid() in system(), that's why system always returns -1.

But what puzzles me more is that: isn't SIGCHLD ignored by default? So why ignoring SIGCHLD explicitly would result in such case?

Could someone explain this to me?

Thanks to @cnicutar now I understand the effects of ignoring SIGCHLD.

But now I'm wondering is there any methods to get the return value of child process while SIGCHLD is ignored? Or is this just impossible due to the POSIX specification and OS realizaiton?

fabregaszy
  • 496
  • 6
  • 23
  • You might find either or both of these useful — they both have the same program as part of my answer: [Do I need to do anything with a SIGCHLD handler if I am just using `wait()` to wait for one child at a time?](http://stackoverflow.com/questions/18437779/do-i-need-to-do-anything-with-a-sigchld-handler-if-i-am-just-using-wait-to-wai/18438562#18438562) and [Linux — sleep of parent process interrupted by child process](http://stackoverflow.com/questions/20016194/linux-sleep-of-parent-process-interrupted-by-child-process/20016488#20016488). – Jonathan Leffler Jul 30 '14 at 14:48
  • No: there is no (standard) way to get the exit status of child processes when you've said you don't care about the exit status of child processes, which is what you've done when you set the signal handling for `SIGCHLD` to `SIG_IGN`. – Jonathan Leffler Jul 30 '14 at 14:55

1 Answers1

4

But what puzzles me more is that: isn't SIGCHLD ignored by default?

No, by default it is not ignored. By default there is simply no handler and no action is taken.

So why ignoring SIGCHLD explicitly would result in such case?

Ignoring SIGCHLD has an interesting side-effect: children don't become zombies.

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD.

That is, you don't need to wait any longer for children since they get collected automatically. But system(3) expected a child! So waitpid returns an error and system(3) behaves.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • Thanks! Then is there anyway possible that I can get the return value of the command while SIGCHLD is ignored? – fabregaszy Jul 30 '14 at 14:42
  • 1
    If you look at the POSIX specification for [``](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html), you will find that the default behaviour for `SIGCHLD` is documented as `I` (ignore). However, that is the setting for `signal(SIGCHLD, SIG_DFL)`, which is distinct from the setting for `signal(SIGCHLD, SIG_IGN)`. Confusing! – Jonathan Leffler Jul 30 '14 at 14:45
  • @fabregaszy No, I think once you ignore SIGCHLD there's no way to get the return code. JonathanLeffler: smashing bit of info, thanks! – cnicutar Jul 30 '14 at 14:49
  • @cnicutar I think, If you want the return you can dynamically change the signal handler to `DFT` in between & then change it to `IGN` again after system. Avoid zombies & get system returns as well. Let me know if my understanding is correct.. – pOrinG Jun 20 '18 at 09:48