civodul pushed a commit to branch devel
in repository shepherd.

commit 07d47592f417ea0e01d58d7fbd0de87b356ddb43
Author: Ludovic Courtès <[email protected]>
AuthorDate: Sun May 5 12:13:56 2024 +0200

    service: ‘pid->process’ no longer captures /proc/PID/cmdline.
    
    Capturing /proc/PID/cmdline at the time ‘pid->process’ is called could
    lead to wrong results in the case PID hadn’t called ‘exec’ yet.  This
    was observed with the ‘guix-daemon’ service, which uses
    ‘fork+exec-command’.
    
    * modules/shepherd/service.scm (<process>)[command]: Rename accessor to
    ‘process-initial-command’.
    (pid->process): Set #f as the initial command.
    (pid-command-line): New procedure, formerly in ‘pid->process’.
    (process-command): New procedure.
---
 modules/shepherd/service.scm | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 935beab..8d6b969 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -203,20 +203,34 @@
   (process id command)
   process?
   (id      process-id)                            ;integer
-  (command process-command))                      ;list of strings
+  (command process-initial-command))              ;list of strings | #f
 
 (define (pid->process pid)
   "Return a @code{<process>} record for @var{pid}."
-  (process pid
-           (catch 'system-error
-             (lambda ()
-               (call-with-input-file (string-append "/proc/"
-                                                    (number->string pid)
-                                                    "/cmdline")
-                 (lambda (port)
-                   (string-tokenize (get-string-all port)
-                                    (char-set-complement (char-set #\nul))))))
-             (const '()))))
+  ;; PID is typically the result of a 'fork+exec-command' call.  There's a
+  ;; possibility that that process has not called 'exec' yet, so reading
+  ;; /proc/PID/cmdline right now would give the wrong result (the command line
+  ;; of the parent process).  Instead, set the command to #f to delay /proc
+  ;; access.
+  (process pid #f))
+
+(define (pid-command-line pid)
+  "Return the command line of @var{pid} as a list of strings, or the empty list
+if it could not be obtained."
+  (catch 'system-error
+    (lambda ()
+      (call-with-input-file (string-append "/proc/"
+                                           (number->string pid)
+                                           "/cmdline")
+        (lambda (port)
+          (string-tokenize (get-string-all port)
+                           (char-set-complement (char-set #\nul))))))
+    (const '())))
+
+(define (process-command process)
+  "Return the command @var{process} is running."
+  (or (process-initial-command process)
+      (pid-command-line (process-id process))))
 
 (define-record-type-serializer (process->sexp (process <process>))
   ;; Serialize all of PROCESS so clients can display more info.

Reply via email to