From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
To: guile-user@gnu.org
Subject: Lost input when using suspendable read-line
Date: Mon, 23 Aug 2021 00:04:46 -0400 [thread overview]
Message-ID: <87mtp8vmap.fsf@gmail.com> (raw)
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
next reply other threads:[~2021-08-23 4:04 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-23 4:04 Maxim Cournoyer [this message]
2021-08-23 21:45 ` Lost input when using suspendable read-line Leo Prikler
2021-08-24 2:03 ` Maxim Cournoyer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87mtp8vmap.fsf@gmail.com \
--to=maxim.cournoyer@gmail.com \
--cc=guile-user@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).