civodul pushed a commit to branch main
in repository shepherd.

commit e5b499c83b4e3a7f070edd7996cebaa485a67316
Author: Ludovic Courtès <[email protected]>
AuthorDate: Sun Mar 2 17:19:58 2025 +0100

    logger: Use ‘put-string’ rather than ‘simple-format’ to avoid deadlocks.
    
    Fixes a bug whereby ‘tests/syslog-slow-output.sh’ would occasionally
    hang, with the ‘shepherd’ process waiting forever in poll(2):
    
      #0  0x00007fd674ef94bf in poll ()
         from /gnu/store/…-glibc-2.39/lib/libc.so.6
      #1  0x00007fd6753de345 in port_poll (
          port=port@entry=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>,
          events=events@entry=4, timeout=timeout@entry=-1)
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/ports.c:1422
      #2  0x00007fd6753e0f59 in scm_i_write_bytes (
          port=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>, 
src="#<vu8vector>" = {...},
          start=0, count=22) at 
/tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/ports.c:2884
      #3  0x00007fd6753e2ef1 in scm_c_put_latin1_chars (
          port=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>, 
chars=<optimized out>, len=22)
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/ports.c:3458
      #4  0x00007fd6753e86df in iprin1 (exp="t-syslog-logger-86.scm",
          port=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>, 
pstate=0x7fd670f19d98)
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/print.c:687
      #5  0x00007fd6753e892a in scm_iprin1 (exp=<optimized out>, 
port=<optimized out>,
          pstate=<optimized out>)
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/print.c:561
      #6  0x00007fd6753e8afd in scm_prin1 (exp="t-syslog-logger-86.scm",
          port=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>, writingp=0)
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/print.c:840
      #7  0x00007fd6753e92d0 in scm_simple_format (
          destination=#<port #<port-type file 7fd674c0cb40> 7fd674d13980>, 
message="~a[~a] ",
          args=("t-syslog-logger-86.scm" 119))
          at /tmp/guix-build-guile-3.0.9.drv-0/guile-3.0.9/libguile/print.c:1198
    
    This is because ‘simple-format’ is not suspendable and
    ‘scm_i_write_bytes’ unconditionally calls ‘poll’ when the output port is
    not ready.  In the test this would lead to a deadlock where output from
    $logger would no longer be consumed by shepherd.
    
    * modules/shepherd/logger.scm (service-builtin-logger): Use ‘put-string’
    instead of ‘simple-format’ to write to ‘log-output-port’.
---
 modules/shepherd/logger.scm | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/modules/shepherd/logger.scm b/modules/shepherd/logger.scm
index 031fa33..2e0e891 100644
--- a/modules/shepherd/logger.scm
+++ b/modules/shepherd/logger.scm
@@ -317,14 +317,12 @@ to @var{history-size} lines in memory."
                                  (process-id process))
                                 (value
                                  value)))))
-                (now (current-time)))
-           (if (integer? pid)
-               (simple-format (log-output-port) "~a[~a] "
-                              command pid)
-               (simple-format (log-output-port) "[~a] "
-                              command))
-           (put-string (log-output-port) line)
-           (newline (log-output-port))
+                (now (current-time))
+                ;; Note: 'simple-format' is not suspendable, hence 
'put-string'.
+                (line* (if (integer? pid)
+                           (simple-format #f "~a[~a] ~a~%" command pid line)
+                           (simple-format #f "[~a] ~a~%" command line))))
+           (put-string (log-output-port) line*)
            (loop pid
                  (ring-buffer-insert (cons now line)
                                      messages)

Reply via email to