`kill-process` is working in your case. But `get-buffer-process` is, after killing `cat`, returning the name of a different buffer (eg *scratch*). You can check this if you insert `(sit-for 1)` into your while-loop. Then you will get the debugger. (let ((buf "*Async Shell Command*")) (async-shell-command "cat") (while (get-buffer-process buf) (sit-for 1) (message "still has proc") (kill-process (get-buffer-process buf)))) To solve this, you should rewrite your code to something like this: (let ((buf "*Async Shell Command*")) (async-shell-command "cat") (while (not (string= (kill-process buf) buf)) (sit-for 1) (message "still has proc")))