Fork, execlp and kill. Zombie process
You should call waitpid(2) or some other waiting system call (wait4(2)...) to avoid having zombie processes. BTW you may also handle the SIGCHLD
signal to be notified when a child process has terminated (or changed state).
Generally, you'll better first kill(2) a process with SIGTERM
(and only later, with SIGKILL
) since that process -your backup.sh
script- could handle correctly (using trap
builtin in the shell script) the signal (but SIGKILL
cannot be caught, and the backup could e.g. leave clutter or useless files on the disk). See also signal(7) & signal-safety(7)
Read Advanced Linux Programming (we can't explain what is taught by that freely available book in several chapters in only a few paragraphs).
BTW, better use perror(3) or strerror(errno)
in messages when a system call fails.
Perl fork(), exec() and then kill creating zombie process
You should use waitpid
in parent process after killing the child process. That's because you use fork
to get a new process, Perl wouldn't do the clean-up job for you as in system
.
But I recommend a better module in CPAN which does the whole messy thing, I find it very convenient.
Fork / exec leaving zombie processes even with signal
The SIG_IGN
setting is not retained across fork()
, so you need to call signal(SIGCHLD, SIG_IGN);
in the child process with the loop that spawns all the commands, not the original parent process.
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
pid_t pid, sid;
pid = fork();
if (pid < 0)
{
perror("fork");
exit(EXIT_FAILURE);
}
if (pid > 0)
{
exit(EXIT_SUCCESS);
}
signal(SIGCHLD, SIG_IGN);
umask(0);
sid = setsid();
if (sid < 0)
{
perror("setsid");
exit(EXIT_FAILURE);
}
if ((chdir("/")) < 0)
{
perror("chdir");
exit(EXIT_FAILURE);
}
while (1)
{
// Check conditions
if (true)
{
pid_t pid2, sid2;
pid2 = fork();
if (pid2 == 0)
{
sid2 = setsid();
// Define command_argv
execlp("sleep", "sleep", "1", (char*)0);
}
}
sleep(60);
}
exit(EXIT_SUCCESS);
}
fork 100 processes at same time and sometimes some processes become zombie
Signals are not queued. If a SIGCHLD is raised while one is pending (probably while your code is in the write
syscall), the program will receive just one notification.
The correct way to handle this is to loop in your handler, until all finished children are reaped:
void sig_handler(int signo) {
pid_t pid;
int stat;
while ((pid = waitpid(-1, &stat, WNOHANG) > 0)
if (WIFEXITED(stat))
{
// Don't actually do this: you should
// avoid buffered I/O in signal handlers.
std::cout << "count:" << ++cnt
<< ", pid:" << pid
<< " signal:" << signo
<< std::endl;
}
}
As mentioned in comments, you should stick to the documented async-signal-safe functions in signal handlers. Buffered I/O (including use of std::cout
) can be risky, as the signal handler could be invoked whilst it's manipulating its internal structures. The best way to avoid problems is to limit yourself to communicating with the main code using volatile sig_atomic_t
variables.
Why does a process create a zombie if execv fails, but not if execv is successful and terminates?
If you don't want to create zombies, your program has to reap zombie processes no matter if they call execv
or not call it or no matter if the execv
call succeeds. To reap zombie processes "automagically" handle SIGCHLD signal:
void handle_sigchld(int sig) {
int saved_errno = errno;
while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
errno = saved_errno;
}
int main() {
signal(SIGCHLD, handle_sigchld);
// rest of your program....
}
Inspired (no... ripped off) from: this link.
Or maybe you want only to reap only this specified child, because later you want to call fork()
and handle childs return value. Then pass the returned pid
from fork()
in your parent to the signal handler and wait
on this pid in sigchld if needed (with some checking, ex. if the pid already finished then ignore future SIGCHLD etc...).
C: Exec/fork Defunct processes
First your second question!
Your children stay in 'zombie' mode because the kernel thinks you might still want to retrieve a return value from them..
If you have no intention to get return values from your child processes, you should set the SIGCHLD signal handler in the parent process to SIG_IGN to have the kernel automatically reap your children.
signal(SIGCHLD, SIG_IGN);
The first question depends a it on your implementation..
But general speaking, just after you fork() you should use close()
to close the old file descriptors for 0 and 1 and then use dup2()
to set them to your wanted values.. No time for an example right now, but hope this pushes you in the right direction..
How to kill a zombie process which always initiated whenever geany does
You can't kill a zombie process since it's already dead.
On Unix and Unix-like computer operating systems, a zombie process or
defunct process is a process that has completed execution (via the
exit system call) but still has an entry in the process table: it is a
process in the "Terminated state".
(from Wikipedia)
It's simply an entry in the process table with no associated process. It exists because the spawning (parent) process has yet to collect the return status (via wait()
). Other than that it will consume no resources.
So I suspect the parent process is either busy or not working properly. I would first of all try to identify that process (via the PPID
column in ps
, for example)
EDIT: I note there's a geany issue raised/resolved around this
Related Topics
Finding All Directories That Are World Readable
Vue Npm Run Serve Failed to Load Resource: Net::Err_Content_Length_Mismatch
Counting Lines Starting with a Certain Word
Influxdb Not Asking for Authentication
(Mac) Leave Core File Where The Executable Is Instead of /Cores
Linux Compile for Enable Uart2
Linking with 32Bit Libraries Under Linux 64Bit
How to Ensure Data Reaches Storage, Bypassing Memory/Cache/Buffered-Io
Setting an Acpi Field in Linux
How to Get Exact List of Collections Form Mongo Database in Shell Script
Does Zgrep Unzip a File Before Searching
Compare Two Files of Different Columns and Print Different Columns
How to Sort Files in Paste Command
Linux Shell Scripting: How to Remove Final Numbers in a Word List File
Shell Exclamation Mark Command