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.