There is a standard method, if the programs cooperate. Run kill -- -42
where 42 is the pid of the parent process. This sends a signal to all the processes in the process group lead by process 42 (the minus sign before the pid means process group).
Normally, if you run your python script from a shell prompt and it simply forks gnuchess
, the two processes should remain in the same process group. But this doesn't seem to be the case, since Ctrl+C sends SIGINT
to the whole foreground process group.
Gnuchess might be in its own process group because it made itself a session leader (but I don't know why it would do this), or because you've double-forked it (python forks a shell which forks gnuchess). A double fork is probably avoidable, but I can't tell you how without seeing your code.
A reasonably reliable and POSIX-compliant way of finding the pid of the gnuchess
process is
gnuchess_pids=$(ps -A -o pid= -o cmd= | awk '$2 ~ /(^|\/)gnuchess$/ {print $1}')
Specific unix variants may have better ways of achieving this, such as pgrep
.
The usual trick is to have something (possibly a signal like SIGUSR1
) trigger the program to fork()
, then the child calls abort()
to make itself dump core.
from os import fork, abort
(...)
def onUSR1(sig, frame):
if os.fork == 0:
os.abort
and during initialization
from signal import signal, SIGUSR1
from wherever import onUSR1
(...)
signal.signal(signal.SIGUSR1, wherever.onUSR1)
Used this way, fork
won't consume much extra memory because almost all of the address space will be shared (which is also why this works for generating the core dump).
Once upon a time this trick was used with a program called undump
to generate an executable from a core dump to save an image after complex initialization; emacs
used to do this to generate a preloaded image from temacs
.
Best Answer
The normal way would be to change the configuration of the monitor program so that it doesn't keep doing that thing you don't want it to do. I'm going to assume you can't do that for some reason, but anything else is a workaround that won't work in all circumstances.
You can't blacklist a process: a process is a runtime entity. The process doesn't exist until it's started. Once it's started, it's too late to prevent it from starting. And how would you identify the process that shouldn't have started, anyway?
You can blacklist a program, or more precisely, a particular installation of a program. All programs are started from an executable file. So if you arrange for the executable file not to exist, it won't start. You could remove it, rename it, or even just make it not executable:
If you don't want or can't modify the filesystem for some reason, but have root access, you could even use a security framework such as SELinux or AppArmor to forbid the monitor from executing this particular program. But that's more complicated.
However, if a monitor keeps trying to respawn that program, it may or may not cope sensibly if the executable disappears. It may spam you (or some log files with error messages).
Assuming that the monitor only keeps the program alive (as opposed to checking the program functionality, e.g. a monitor for a web server process might periodically try to access a web page and restart the server if it isn't responding), you could replace the program by a program that does nothing but block forever. There's no program that does this in the basic utility collection, but you can write one easily:
Depending on why you want to block that program, you may or may not be able to achieve a similar result by suspending the process of the original program, with
pkill -STOP programname
orkill -STOP 1234
where 1234 is the process ID. This keeps the process around, but doing nothing until explicitly resumed (withkill -CONT
). The process won't consume any CPU time, and its memory will get swapped out when the system requires RAM for other things, but it does keep consuming resources such as open files.