0

Is there a way to find out the pid of an emacs subprocess started with call-process?

I realize that the return value of start-process is precisely its pid but I would like to know the pid of a process created with call-process instead.

I know that, after a process has started, I can get information about it using the utility ps, but I'd like to avoid parsing the output of ps just to know the pid.

2
  • I don't see an easy way to do what you want: my impression is that call-process is used when you want to run something and either wait for it to finish (in which case you can check exit status) or let it go async and forget about it. It does not give you any handles to manipulate the process. You'll have to use some of the higher level process primitives for that. But it is only an impression, so maybe I'm missing something.
    – NickD
    Commented Jun 7, 2021 at 13:43
  • Dear Nick, thanks for weighing in! I fully agree with you regarding the intended use of call-process (especially with the parameter DESTINATION set to 0). The trouble I'm having is that the alternative, namely start-process, shuts down when emacs finishes as discussed in my previous question emacs.stackexchange.com/questions/65090/… Should you be able to figure out a way to keep a process started by start-process running after emacs finishes (i.e. to answer my other question), it would fully solve my problem!
    – Ruy
    Commented Jun 7, 2021 at 17:08

1 Answer 1

1

Here's a somewhat silly implementation of a function that does a call-process and returns its pid (sort-of):

(defun call-process-pid ()
  (let (l1 l2)
    (setq l1 (list-system-processes))
    (call-process "sleep" nil 0 nil "60")
    (setq l2 (list-system-processes))
    (cl-set-difference l2 l1)))

It's a somewhat cleaner way of doing a ps before and after to find out what process(es) got added.

The limitation is that between the first and second calls to list-system-processes, a bunch of processes may have been created, so the set difference will have more than one entry: AFAIK, there is no way to know which one is "your" process without looking at each one (e.g. with process-attributes to find out the command that was run). It may also happen that your command runs to completion before the second list-system-processes, in which case it will not appear at all - but that's probably OK for your intended use.

There are ways to daemonize a subprocess: that can be easily done from a C program (Stevens' "Advanced Programming in the Unix environment" has examples, but googling "daemonize Unix" should provide plenty). I'm not sure whether you can do the equivalent from within Emacs, but you don't have to: you can use nohup to prevent the program from responding to SIGHUP, so instead of (call-process "command" nil 0 nil args...), you can do (call-process "nohup" nil 0 nil "command" args...). I have not tested that it actually works, but I can't see any reason why it shouldn't. Assuming that it works, adapting this idea to your previous question should be straightforward.

5
  • Thanks very much Nick! It is an excellent answer and I think the draw-backs you mention are not likely to take place in the application I have in mind, at least not too often. I tested the nohup alternative with mixed results: some times it works, sometimes it does not.
    – Ruy
    Commented Jun 7, 2021 at 22:05
  • That's too bad. Any inkling about the difference? Are you running the same command repeatedly and that sometimes works, but other times not? Does your command produce any output? I assume it does not consume any input, correct?
    – NickD
    Commented Jun 7, 2021 at 22:16
  • I am running emacs -Q --batch --eval '(start-process "Okular" nil "nohup" "okular" "main.pdf")'. Whether or not it works is pretty random. Here is a sample "No No No No Yes No No No No Yes No Yes No No Yes No No Yes No Yes Yes No No No Yes". There is no output regardless of whether or not it works.
    – Ruy
    Commented Jun 7, 2021 at 23:12
  • emacs -Q --batch --eval '(progn (start-process "Okular" nil "nohup" "okular" "main.pdf") (sit-for 1))' seems to work every time.
    – Ruy
    Commented Jun 7, 2021 at 23:41
  • 1
    That's what I was going to suggest as a test: it might be that emacs exits and the process is killed before it even has a chance to start and set up the SIGHUP protection. So delaying the exit a bit helps, but although it's worked so far, it is not guaranteed to always work. Just making the delay bigger will increase the probability of success but it will never be 1.
    – NickD
    Commented Jun 8, 2021 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.