Linux – Can a process be frozen temporarily in linux


I was wondering if there is a way to freeze any process for a certain amount of time?

What I mean is that: is it possible for one application (probably running as root) to pause the execution of another already running process (any process, both GUI and command line) and then resume it later? In other words I don't want certain processes to be scheduled by the linux scheduler for a certain amount of time.

Best Answer

See here

There are two signals that can suspend the execution of a process. One is "graceful", and one is "forceful".

The "graceful" one is SIGTSTP, and its purpose is to "nicely" ask the process, if it feels like it, to please suspend execution until it receives a SIGCONT. In the case of SIGTSTP, the process can ignore SIGTSTP and continue executing anyway, so this requires cooperation from a program that is designed to handle SIGTSTP.

The "forceful" one is SIGSTOP, and its purpose is to suspend all userspace threads associated with that process. It is just as impossible for the process to ignore SIGSTOP as it is for it to ignore SIGKILL (the latter kills the process forcefully).

To send an arbitrary signal, including any of the ones mentioned here, you can use programs such as kill, killall, or pkill; or use the system call kill(2). See your operating system's manpages for platform/architecture/version-dependent details and errata regarding any of the above. Note that the word "kill" in all of these commands and the syscall is a bad misnomer. These commands are not designed, exclusively, to terminate processes. They can do that by sending certain ones of the signals; but signals can also be used for functionality other than terminating a process. For example, SIGSTOP only suspends the process, and it's just one of several signals that can be sent this way.

To add a condition of automatically resuming the process after a period of time has elapsed, you will need to use some sort of monitoring process that remains running and sets a timer in order to wake up the monitoring process, which then in turn calls kill(2) again and sends the SIGCONT signal to the stopped process, in order to request the kernel to resume execution. Note that Linux has several timing mechanisms with various degrees of accuracy and precision; furthermore, if your system is very busy, your monitoring process might not get woken up until well after its timer has expired, and thus the wakeup might be delayed.

If you depend on very accurate precision of suspension and resumption of the suspended process, you may need to run your monitoring program with real-time permissions (see this manpage on sched_setscheduler(2) for information about making your process real-time). You can also use High-Resolution Timers, a feature of the Linux kernel (which is only available if your hardware provides support for them), in combination with real-time scheduling, to get very accurate, sub-millisecond precision on timing, then wakeup and send the signal to resume the monitored process very quickly.

You didn't indicate which technologies you are willing to use to implement this. At a bare minimum, you'll need at least bash scripting, although you won't be able to get very fine-grained timing that way. Here is a bash "script" (untested, so please be careful) that is just a proof of concept of your query. If you need precise timing, you'll have to write a program, probably in C/C++ or another native language, and use real-time scheduling and hrtimers.

#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"

Note that the script will end and the controlling script will terminate, but due to screen controlling the monitor process, it will continue running in the background for 10 seconds (based on the argument passed to sleep) and then wake up and continue the child process. But this will be long after the controlling script has ended. If you want to synchronously wait for the time to elapse, just omit the second call to screen and hard-code the sleep and kill into the controlling script.

You can test that the process does in fact suspend by running

screen -rS child

after you start this script. You won't see anything on the console. Then after the timer expires (10 seconds), it will flood your screen with base64 data (random characters from 0-9 and A-F). Press Ctrl+C to exit.

Related Question