guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 01/02: popen: 'open-process' returns unbuffered ports.


From: Ludovic Courtès
Subject: [Guile-commits] 01/02: popen: 'open-process' returns unbuffered ports.
Date: Fri, 19 Jun 2020 15:10:11 -0400 (EDT)

civodul pushed a commit to branch master
in repository guile.

commit c7f76d94dabb589601e809710de5fcc9c4c9a882
Author: Ludovic Courtès <ludo@gnu.org>
AuthorDate: Fri Jun 19 20:56:38 2020 +0200

    popen: 'open-process' returns unbuffered ports.
    
    * module/ice-9/popen.scm (open-process)[unbuffered, fdes-pair]: New
    procedures.
    Use them.  Return unbuffered ports.
    * test-suite/tests/popen.test ("open-pipe*"): New test prefix.
---
 module/ice-9/popen.scm      | 25 ++++++++++++++++++++-----
 test-suite/tests/popen.test | 23 +++++++++++++++++++++++
 2 files changed, 43 insertions(+), 5 deletions(-)

diff --git a/module/ice-9/popen.scm b/module/ice-9/popen.scm
index 5ab93f2..a0ef0dc 100644
--- a/module/ice-9/popen.scm
+++ b/module/ice-9/popen.scm
@@ -99,13 +99,28 @@ process (based on pipes) is created and returned.  
@var{mode} specifies
 whether an input, an output or an input-output port to the process is
 created: it should be the value of @code{OPEN_READ}, @code{OPEN_WRITE}
 or @code{OPEN_BOTH}."
+  (define (unbuffered port)
+    (setvbuf port 'none)
+    port)
+
+  (define (fdes-pair ports)
+    (and ports
+         (cons (port->fdes (car ports)) (port->fdes (cdr ports)))))
+
   (let* ((from (and (or (string=? mode OPEN_READ)
-                        (string=? mode OPEN_BOTH)) (pipe->fdes)))
+                        (string=? mode OPEN_BOTH))
+                    (pipe)))
          (to (and (or (string=? mode OPEN_WRITE)
-                      (string=? mode OPEN_BOTH)) (pipe->fdes)))
-         (pid (piped-process command args from to)))
-    (values (and from (fdes->inport (car from)))
-            (and to (fdes->outport (cdr to))) pid)))
+                      (string=? mode OPEN_BOTH))
+                  (pipe)))
+         (pid (piped-process command args
+                             (fdes-pair from)
+                             (fdes-pair to))))
+    ;; The original 'open-process' procedure would return unbuffered
+    ;; ports; do the same here.
+    (values (and from (unbuffered (car from)))
+            (and to (unbuffered (cdr to)))
+            pid)))
 
 (define (open-pipe* mode command . args)
   "Executes the program @var{command} with optional arguments
diff --git a/test-suite/tests/popen.test b/test-suite/tests/popen.test
index 86e3889..692156a 100644
--- a/test-suite/tests/popen.test
+++ b/test-suite/tests/popen.test
@@ -196,6 +196,29 @@ exec 2>~a; read REPLY"
             (close-pipe port)
             result))))))
 
+
+ (with-test-prefix "open-pipe*"
+
+   (pass-if-equal "OPEN_BOTH"
+       '(0 (good!))
+     ;; This test ensures that the ports that underlie the read/write
+     ;; port are unbuffered.  If they were buffered, the child process
+     ;; would wait in 'read' forever.
+     (let ((pipe (open-pipe* OPEN_BOTH "guile" "-c"
+                             (object->string
+                              '(begin
+                                 (setvbuf (current-output-port) 'line)
+                                 (write '(hello!))
+                                 (newline)
+                                 (let ((greeting (read)))
+                                   (write '(good!))))))))
+       (setvbuf pipe 'line)
+       (let ((return (read pipe)))
+         (write '(hi!) pipe)
+         (newline pipe)
+         (let ((last (read pipe)))
+           (list (close-pipe pipe) last))))))
+
  ;;
  ;; close-pipe
  ;;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]