Sim
Sim

Reputation: 4185

How to kill process (created by run-process)

I want to kill a process started by (sb-ext:run-program).

(let ((process (sb-ext:run-program "/path/to/process.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-close process)
  (sb-ext:process-kill process 9 :pid))

According to SBCL-Manual (sb-ext:process-kill process 9 :pid) should send SIGKILL (which has value 9) to process, therefore annihilating this process.

But when I am trying to use this using a dummy process:

#!/bin/bash

i=0
while [ $i -lt 4 ]
do
sleep 5
i+=1
done

It leaves a corps behind which cannot even be killed using htop + kill.

The process tree before execution looked like this:

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

During execution:

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- /bin/bash /path/to/process.sh
| | | |- sleep 5
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

After execution (the process.sh will not terminate unless the main sbcl is killed/stopped):

|- /usr/bin/emacs
| |- /usr/local/bin/sbcl
| | |- process.sh
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl
| | |- /usr/local/bin/sbcl

The script can be killed and terminated just fine when started manually and using either Ctr-C or htop + kill.

Therefore how can I achive a seamless/corpsless kill within sbcl?

The same happens when using:

(let ((process (sb-ext:run-program "/usr/local/bin/sbcl" '("--dynamic-space-size" "512" "--eval" "(sleep 100)") :wait nil)))
  (sleep 10)
  (sb-ext:process-close process)
  (sb-ext:process-kill process 9 :pid))

Upvotes: 2

Views: 1683

Answers (2)

mihai
mihai

Reputation: 4722

If you're using the portable uiop:run-program instead of the sbcl's one, you can kill the PID by calling run-program a second time, giving it the kill command, just like you would in the shell:

(uiop:run-program (format nil "kill ~a" (process-info-pid process)))

Where process is the return result of the initial run-program, the one that started the process you want to kill.

Upvotes: 0

Sim
Sim

Reputation: 4185

The solution looks either like this (if you use streams associated with the process you need process-close):

(let ((process (sb-ext:run-program "/home/user/processTest.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-kill process 15 :pid)
  (sb-ext:process-wait process)
  (sb-ext:process-close process)
  (sb-ext:process-exit-code process))   

Or as Sylvester pointed out you can just leave out the process-close (if you do not have any streams associated with the process):

(let ((process (sb-ext:run-program "/home/user/processTest.sh" '() :wait nil)))
  (sleep 10)
  (sb-ext:process-kill process 15 :pid))                                

process-close affects the process in a way that it will become a zombie.

This occurs for child processes, where the entry is still needed to allow the parent process to read its child's exit status.

As soon as the exit status is read via process-exit-code the process is reaped and will disappear.

Upvotes: 4

Related Questions