kill & wait in one step
Asked Answered
M

3

8

If I use a combination to kill a child process in batch and wait for it's termination, I use

kill $PID
wait $PID

If the process exists immediately, the wait will fail, since the pid is not running anymore.

Is there a way to combine both statements to a single one to aviod the error?

Edit: The process I have to kill uses a tempfile; thus it has to be closed (and not just signaled to close) to start it again. Checking the return value of kill does not help, since this indicates whether the signal was delivered successfully.

Mongo answered 10/6, 2015 at 7:55 Comment(11)
What is the purpose of your wait? What do you really want to do?Incessant
You know that kill already returns a code that you can check to see if it was successful, right? ;-) If you want to kill the process no matter what, you can try kill -9 $PID.Electroballistics
If you want to execute commands sequentially it is a good idea to check out $$ ; || etc. Otherwise, maybe a while loop can help you out. while [ $(kill ${PID}) ]; do "nothing" ;doneMotoneuron
@SigveKarolius Wrong. kill $PID returns immediately regardless of whether the job is actually killed or not. Just write a simply script that traps and ignores SIGINT, and see how kill works (it will return 0, although the job is not killed).Unconnected
Then I'm afraid you need to find something else... Why not use some polling to wait until some event (as the creation of a file named closeDone make by the process)? Or make the process sleep for a while before exiting? Make the script sleep for a while after killing? Note that the latests are almost tricky. Do you have control over the source code of the process?Incessant
Regarding what you want to do: why don't you use a unique tempfile each time? (Check out mktemp.)Unconnected
Also, a not-so-safe way is to simply check whether the PID still exists.Unconnected
Sorry about my ignorance of how kill works. Let me try some more ignorance: maybe you can use ps to check the status of the process after using kill?Motoneuron
You can use while kill $PID 2>/dev/null; do sleep 0.01; done. After PID exits, kill will fail & loop will break. There is a possibility of race condition though - another process may start in that 0.01 second, which can possibly have same PID...Hirundine
@4ae1e1: Because the binary I have to kill can not be changed.Mongo
@SigveKarolius: I don't want to do this, because the pid might be used again in the meantime by another process. Then, it'd be better to use wait, since this guarantees that the process is at least a child process.Mongo
R
9

It's not a one-liner, but would you be willing to consider spawning off the kill with a short sleep, then waiting in the main thread? Something like:

(sleep 1; kill $PID) &
wait $PID

This addresses your concern of the PID being reused after the kill. Even if you reduce the sleep to something much smaller, it introduces idle time, but it should at least ensure that you wait on the correct process.

Rochet answered 10/6, 2015 at 13:24 Comment(1)
Not as elegant as I hoped, but an interesting idea!Mongo
G
2

Effectively, there is not an atomic kill and wait since they are two separate system calls. Some wrapper must be written to execute both functions.

If you do not care about the status,

kill $PID 2> /dev/null
wait $PID 2> /dev/null

If you do care about the status, but do not want an error message, do something like

if ! kill $PID 2> /dev/null; then
    # Error logic here
fi

The fancy way for both is a function

killAndWait() {
    kill $1 2> /dev/null && wait $1 2> /dev/null
}

Then, do

killAndWait $PID
Glaudia answered 10/6, 2015 at 13:20 Comment(1)
They may be two separate syscalls, but at the syscall level, wait() is a valid and expected thing to do on a process that you've just killed. I can't speak to what kill and wait's semantics are in Bash, though.Gannet
G
0
kill $PID
wait $PID

If the process exists immediately, the wait will fail, since the pid is not running anymore.

As long as $PID really points to a child process of the shell, I don't think wait will fail. I don't see an error with your code.

Experiment:

bash-3.2$ while : ; do ls > /dev/null ; done &
[1] 44908
bash-3.2$ kill 44908
[1]+  Terminated: [...]
bash-3.2$ wait 44908
bash-3.2$ echo $?
143

143 is the return code for SIGTERM, so the kill worked as expected, and Bash could wait for the dead process.

Gannet answered 12/5, 2021 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.