Subject: Re: [PATCH 1/2] services: shepherd: Provide the right #:kernel-log-file on the Hurd.

From: [email-masked]
Date: Sun, 17 Aug 2025 20:46:44 +0200 (CEST)

Hi.
Aug 17, 2025, 15:19 by [email-masked]:

>
>
> So you have a patch for /hurd/streamio and a C reproducer?  (Maybe you
> sent it already and I haven’t seen.)
>
No i have not sent this:
Something like this fixes the D_WOULD_BLOCK errno.
--8<---------------cut here---------------start------------->8---
diff --git a/trans/streamio.c b/trans/streamio.c
index e42ff908..93057146 100644
--- a/trans/streamio.c
+++ b/trans/streamio.c
@@ -1049,6 +1049,8 @@ device_read_reply_inband (mach_port_t reply, kern_return_t errorcode,
 
   input_pending = 0;
   err = errorcode;
+  if (err == D_WOULD_BLOCK)
+    err = EWOULDBLOCK;
   if (!err)
     {
       if (datalen == 0)
--8<---------------cut here---------------end--------------->8---

Some c code that runs fgets in a loop until an error
--8<---------------cut here---------------start------------->8---
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#define _PATH_KLOG "/dev/klog"

int
main ()
{

  ssize_t n;
  int fd;
 
  fd = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK | O_CLOEXEC);

  if (fd < 0)
    {
      perror("open");
      exit(EXIT_FAILURE);
    }

  FILE* file = fdopen(fd, "r");
  
  char* line;
  int line_max = 1024;

  line = malloc(line_max +1);

  if(line == NULL)
    {
      perror("malloc");
      exit(EXIT_FAILURE);
    }

  // The first read always fails with EWOUDLBLOCK
  fgets(line, line_max +1 , file);
  perror("fgets");
  errno = 0;
  while(fgets(line, line_max +1 , file) != NULL)
    {
      printf("%s", line);
    }
  perror("fgets");
  
  free(line);
  close(fd);
  exit(EXIT_SUCCESS);
}
--8<---------------cut here---------------end--------------->8---

I am using `(cross-gcc-toolchain "i586-pc-gnu")` to get a cross compiler with a bit of a hack to remove the %hurd-system supported-system restriction from the hurd and mach headers.

>> However this does not really help the shepherd syslog because guile's
>> read-line blocks forever waiting for a terminating newline. Also guile
>> is unaware that further attempts to read would EWOULDBLOCK as "(select
>> (vector port) #() #() 0)" indicates that reading is possible but then
>> actually trying to a get a char blocks.
>>
>
> Ah but I think that’s fine: shepherd, suspendable ports are enabled (via
> Fibers), which means that read attempts that return EAGAIN or
> EWOULDBLOCK result in the calling fiber being suspended.
>
> You would need to try this for real, but it should be fine.
>

It is fine in the sense that fibers suspends the system-log successfully at the "end" of /dev/klog.
However It is not fine because it will never wake up it up again. 
According to the c example it now returns EWOULDBLOCK as expected.From testing around a bit I think it might be (@ (ice-9 rdelim) read-line) waiting for a terminating newline.
And again when I retried this just now there was the noticable delay with anything shepherd when the shepherd-syslog is running (default (system-log-configuration) configuration)

> Thanks!
> Ludo’.