QMI SDK: SLQSStart() sets signal SIGCHLD to SIG_IGN

It appears that SLQSStart() is changing the state of signal SIGCHLD to SIG_IGN, which affects the calling process. Any subsequent system calls that rely on wait(), waitpid(), system() etc… fail with an ECHILD (no child process) error.

Whilst it is common to set SIG_CHLD to SIG_IGN when ‘daemonizing’ an application, this is usually done AFTER a fork(), and hence the signal change only affects the ‘new’ child process.

Why is SLQSStart() changing a signal that affects the calling process? Is this a known bug?

[SLQS04.00.18 pre-compiled ARM binary] [I don’t have access to the SDK source code]

In 04.00.18 source code, the code is like
/* prevent child became zombie */
signal(SIGCHLD, SIG_IGN);

/* start SDK process */
pid = fork();

I’m checking with the team and will get back soon.

Hi dwen,

Thanks for the update.
I understand the need for the QMI SDK to prevent itself from becoming a ‘zombie’, but to avoid the situation I have described in my original post it would be usual to perform a ‘double fork’ e.g.

fork();  /* 1st to isolate the calling process from the up-coming signal change */
signal (SIGCHLD, SIG_IGN);  /* change SIGCHLD to IGNORE */
fork();  /* start new process */

Obviously the above is just the bare outline…A full example can be seen at: https://stackoverflow.com/questions/17954432/creating-a-daemon-in-linux#

Thanks a lot for the explanation and suggestion! I’ve forwarded it to our team for their consideration
(They just explained the reason/history of the ‘zombie’ fix and they are having other people to review the fix)

“We will not fork twice in swi_osapi.c since we only need to have one child process which is slqssdk. The parent process in this case is the application which calling the SLQSStart(). We do not need to know the child process’s status as long as it was launched successfully. The parent process will communicate with the child process using IPC socket later on. If the child process is dead or became zombie, the QMI transactions will be stuck and the API will return failure. There will be some error logs indicated in the syslog.”

Hi dwen

Yes, but going back to my original post…By changing signal SIGCHLD to SIG_IGN before the fork you are (also) changing the signal SIGCHLD within the parent process (the application calling SLQSStart()). This causes a problem within the application when calling functions such as ‘system()’ - which may be commonly used, such as when manipulating network adapter settings e.g.

system(“ip link set dev_name up”);

Although system() will complete it will return -1 (meaning error) with errno set to 10, ECHILD. This is because system() forks a child process and uses wait() (or waitpid) but there is no pending child - because you have set signal SIGCHLD to SIG_IGN. See post c++ - system() always returns non-zero when called as CGI - Stack Overflow

As this post suggests, the application could probably safely restore the signal setting when in a single threaded application. But I am multi-threaded, which means there would always be a race between a thread that was using system() and a thread that was calling SLQSStart(). Further, this seems like a ‘fudge’, and surely can’t be what the SDK developers intended?