unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Lost input when using suspendable read-line
@ 2021-08-23  4:04 Maxim Cournoyer
  2021-08-23 21:45 ` Leo Prikler
  0 siblings, 1 reply; 3+ messages in thread
From: Maxim Cournoyer @ 2021-08-23  4:04 UTC (permalink / raw)
  To: guile-user

Hello,

I'm pretty new to this, so hopefully I'm doing something wrong, but when
using a suspendable read-line with the following "minimal" program:

--8<---------------cut here---------------start------------->8---
(use-modules (ice-9 match)
             (ice-9 rdelim)
             (ice-9 suspendable-ports))

(install-suspendable-ports!)

(define (read-line* port cont)
        ;; Return, as a pair, the line and the terminated delimiter or end-of-file
        ;; object.  When a line cannot be read, return the '(suspended
        ;; . partial-continuation) pair, where partial-continuation can be
        ;; evaluated in the future when the port is ready to be read.
        (call-with-prompt 'continue
          (lambda ()
            (parameterize ((current-read-waiter
                            (lambda (_)
                              (abort-to-prompt 'continue))))
              (if cont
                  (cont)
                  (read-line port 'split))))
          (lambda (partial-continuation)
            (cons 'suspended partial-continuation))))

(define (main)

  ;; Create a pipe, and set its read side to non-blocking mode.
  (define child->parent-pipe (pipe))
  (let ((flags (fcntl (car child->parent-pipe) F_GETFL)))
    (fcntl (car child->parent-pipe) F_SETFL (logior O_NONBLOCK flags)))

  ;; Empty buffers to avoid duplicated output.
  (flush-all-ports)

  (match  (primitive-fork)
    (0                                  ;child

     ;; Connect the stdout and stderr outputs of the child process to the
     ;; pipe established in the parent.
     (close (car child->parent-pipe))   ;unused input pipe
     (dup2 (port->fdes (cdr child->parent-pipe)) 1)
     (dup2 1 2)

     (set-current-output-port (cdr child->parent-pipe))
     (set-current-error-port (cdr child->parent-pipe))

     (while #t
       (format #t "Line 1\n")
       (format #t "Line 2\nLine 3\n")
       (display "Done!\n")
       (force-output)

       (sleep 5)))

    (child-pid                          ;parent

     (close (cdr child->parent-pipe))   ;disconnect the write end of the pipe

     (define port (car child->parent-pipe))

     (let loop ((cont #f))
       (match (select (list (port->fdes port)) '() '())
         (((fdes ..1) () ())
          (let next-line ((line+delim (read-line* port cont)))
            (match line+delim
              (('suspended . partial-continuation)
               (loop partial-continuation))
              ((line . _)
               (format #t "~a~%" line)
               (next-line (read-line* port cont)))))))))))

(main)
--8<---------------cut here---------------end--------------->8---

The output looks like this (non-deterministic it seems):

--8<---------------cut here---------------start------------->8---
$ guile repro.scm
Line 1
Line 2
Line 3
Done!
Line 1
Line 2
Line 3
Done!
Line 1
Line 1
Line 1

[...]
--8<---------------cut here---------------end--------------->8---

And strace shows that more than a single line is buffered on each
read-line, but that it only returns the first line of such buffered
input:

--8<---------------cut here---------------start------------->8---
read(8, 0x7fcd06bfc020, 4096)           = -1 EAGAIN (Resource temporarily unavailable)
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
select(9, [3 8], [], [], NULL)          = 1 (in [8])
read(8, "Line 1\nLine 2\nLine 3\nDone!\n", 4096) = 27
write(1, "Line 1", 6Line 1)                   = 6
write(1, "\n", 1
)                       = 1
read(8, 0x7fcd06bfc020, 4096)           = -1 EAGAIN (Resource temporarily unavailable)
rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
select(9, [3 8], [], [], NULL)          = 1 (in [8])
read(8, "Line 1\nLine 2\nLine 3\nDone!\n", 4096) = 27
write(1, "Line 1", 6Line 1)                   = 6
write(1, "\n", 1
)                       = 1

[...]
--8<---------------cut here---------------end--------------->8---


Bug?  PEBCAK?  I'm interested to know :-).

Thanks,

Maxim



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-08-24  2:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-23  4:04 Lost input when using suspendable read-line Maxim Cournoyer
2021-08-23 21:45 ` Leo Prikler
2021-08-24  2:03   ` Maxim Cournoyer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).