Receiving SIGCHLD yet have spawned no child processes - c

I have a C program running on Linux 3.12. This program spawns several child processes. One of these processes spawns a thread that runs for a bit then terminates. While this child process is running it performs an epoll_wait(). Periodically, the epoll_wait returns with an EINTR error. I setup the child process to catch the signal doing this interruption and found it is a signal 17, which, according to everything I have read is a SIGCHLD. Thing is, the thread this child process spawned is still running. It did not terminate. I also thought that threads do not generate a SIGCHLD on termination.
Any thoughts on why my process may be getting a signal 17?

The answer is a call to system(). This function in the code spawns a process to execute the shell command being passed in. The thread was calling system() to run some shell commands. When they finished the processes that was spawned ended and generated the SIGCHLD.

Related

Get signal when tid status change

There is a way to look when pid/tid status change with waitpid but this is blocking function.
I want to monitor all threads in specific pid and get signal when one of them change and print the tid.
For now I open threads as count of threads in that process and each 1 make waitpid on 1 tid and after that blocking function finish I print that tid that changed.
How can I get a signal that tid change so I can monitor all tid's in 1 thread.
I didn't want to monitor all pid in system only specific pid/tid.
Those tids/pids are not children of my process.
You can call
int status;
pid_t waitpid(-1, &status, 0);
to wait for any child process change.
So you do not have to specify in advance, which pid to monitor, and can react on any status change. This way you do not need to start one thread for each pid.
As to the signal part of your question: A SIGCHLD is sent to your process when a child process exits. This signal is ignored by default, but you can install a custom signal handler for it, of course.
If you only want to reap specific pids, linux provides the option WNOWAIT, which only reports the state, but does not really reap the child process. Now you can check, if the pid is one of those you want to monitor, and if so, call waitpid() again without the option.
If the processes are not children, waitpid() cannot be used in general. One option is, to attach with ptrace() to these 40 processes to get signalled, if one of these processes exit. This might have unwanted side-effects, however.
If you're using POSIX threads, then you could use pthread_cleanup_push and pthread_cleanup_pop to call a "cleanup" function when your thread is exiting.
This "cleanup" function could then send one of the user signals (SIGUSR1 or SIGUSR2) to the process which then catches it and treats it as a signal about thread termination.
If you use sigqueue you can add the thread-id for the signal handler so it knows which thread just exited.
You can use pthread_sigmask to block the user signal in all threads, to make sure it's only delivered to the main process thread (or use pthread_sigqueue to send to the main process thread specifically).

C Linux Signal Handler for the Main Process Only

I am making a program that creates numerous processes using fork(), which then calls an exec function to the same program (this is required by the professor).
I need it to react to CTRL+C (SIGINT) and ask the user if he/she wants to leave. The problem is that the signal handler is implemented in all the child processes too, so, when the signal is sent, the user has to answer the same amount of times as the number of processes.
I only want it to ask the user once per CTRL+C.
What solutions can I implement?
When you call fork(), the parent process will get back the pid of the child. You can send a SIGTERM or SIGKILL signal to the children through the kill syscall when the parent receives the SIGINT signal.
You can set a global variable pid and populate it with the result of getpid() on launch. And inside the signal handler test getpid() against pid then execute your code. Something like, if you are the main process please proceed, if not exit!
End result: You will have a signal handler that is run once by the main process....

C - Atomic killpg

I have process which forks a lot. Child processes do lot of stuff and another system calls.
When ANY child process gets error from system call, it prints error description to stderr and send SIGUSR1 to group leader (main parent process).
SIGUSR1 tells parent to kill all child processes, free resources and exit program execution (to avoid zombie processes).
I need to kill all children at once. Atomically. So when any error happens in ANY child process, all child processes stops with their work immediately.
Currently parent process kills all child processes with SIGUSR2 - It sends this signal to all process group members (killpg) - all of them have signal handler installed which kills them (exit) - group leader won't get killed though (it still needs to free resources).
The problem is that before all child processes get killed, they still can execute about 1-2 rows of code, which is not what I want. I need to stop them immediately.
How can I achieve this?
Signals are delivered in a async fashion, since both parent and child processes are running, you cannot expect the child process will handle the signal immediately when parent send the signal.
The problem is that before all child processes get killed, they still can execute about 1-2 rows of code, which is not what I want. I need to stop them immediately.
Your problem is more of a coordination and synchronization between processes, rather than signal handles. There are two ways I can think of:
Use synchronized signals. That is when each child send SIGUSR1 to the parent, they stop working, and wait on SIGUSR2 signal by the waiting functions, like sigtimedwait, or sigwait, in this way, they will not run any additional code before exiting.
Use pipe or socketpair to create communication channels between parent and children, that is, parent send kill instruction to children, and each child will free necessary resources and kill themselves. This requires children to listen on the channel while doing work.
Do you mean that all child processes must stop working as soon as the faulty child send SIGUSR1 ?
If this is what you want, I don't think you can achieve this the way you are doing: when the faulty child sends SIGUSR1 to the leader, the other childs will continue execution until the SIGUSR1 is processed by the leader.
Do you really need the faulty process to send SIGUSR1 first to the leader ? Would not this be possible that the faulty process directly sends SIGUSR2 to the group, which signal can just be ignored by the leader (or, at least, not processed as a termination signal) ?

Is kill function synchronous?

Is the kill function in Linux synchronous? Say, I programatically call the kill function to terminate a process, will it return only when the intended process is terminated, or it just sends the signal and return. If that is the case, how can I make it wait for the intended process to be killed?
No, since it doesn't kill anything, it only sends a signal to the process.
By default this signal can even be blocked or ignored.
You can't block kill -9 which represents sending SIGKILL
To wait for the process to die:
while kill -0 PID_OF_THE_PROCESS 2>/dev/null; do sleep 1; done
kill cannot be synchronous as it only sends a signal. The target process might ignore incoming signals (cf. SIG_IGN) so there's no guarantee regarding kill's effect.
It shouldn't be difficult to make an experiment verifying this hypothesis. Start process A and make it handle SIGTERM with a 10 second sleep before dying. Then start process B, which delivers a SIGTERM to A and exits immediately.
The kill system call does not wait for the other process to do anything. The signal is posted to the target process and the system call returns. The target process notices the signal when it is scheduled to run.
No. man 2 kill
man wait
See also man 7 signal for more details about Unix signals.

How to kill the parent process and its children on ctrl+C or ctrl+Z

I have the main process in my program that fork() some children processes and then goes into endless loop (Also, the children processes are endless). Now, I want to kill all processes, close a socket, de-attach shared memory, and clean all similar stuff on terminating the program with Ctrl+C or Ctrl+Z. I search the internet and I found that I could do that by sending some signals like SIGSTOP and SIGINT, but I don't know how to do it.So, how can I accomplish this in my program?
From outside the program, you can send any process a signal using the kill command.
By default, kill will send the SIGTERM signal, which will terminate a process, and free its allocated resources. You can use the ps command to find the process ids of your program's processes. Using CTRL-C will only terminate the parent process. It will not kill the child processes. If you just forked, and didn't exec a new program, then all of your child processes will have the same name as the parent, which means you can use the killall command to terminate them all in one go. If you are logged in remotely, then logging out will cause a SIGHUP signal to be sent to all of the processes you spawned during the session, which will terminate them by default.
From inside the program, there is a kill() function that operates similar to the command. You will need the process ids still, so it's important that your parent code remembers the child process id returned by fork.
When your process exits brutally, all resources are certainly freed.
However, if you want to control the behaviour (what order, etc, I don't know what) then you should install a signal handler. See sigaction(2).

Resources