unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
From: Josselin Poiret <dev@jpoiret.xyz>
To: Zelphir Kaltstahl <zelphirkaltstahl@posteo.de>
Cc: guile-user@gnu.org
Subject: Re: Shell commands with output to string
Date: Wed, 09 Mar 2022 15:14:21 +0100	[thread overview]
Message-ID: <87r17bmcw2.fsf@jpoiret.xyz> (raw)
In-Reply-To: <3080f6d4-e341-13a8-81e1-a6c7f6a3efb2@posteo.de>

Hello Zelphir,

Zelphir Kaltstahl <zelphirkaltstahl@posteo.de> writes:
> I have questions regarding this workaround:
>
> Can you explain how and why this works? I have tried to make sense of it and 
> here are my notes so far (reference: 
> https://notabug.org/ZelphirKaltstahl/guile-examples/src/2dead9f7bb9b40fc26eb490a93e1dc7abca7252c/shell/system-asterisk-stdout-to-stderr-redirection-bug.scm):

Note that here, I used undocumented behavior of open-pipe*, which can be
understood by inspecting libguile/posix.c (look for piped-process) and
module/ice-9/popen.scm (look for open-pipe*).

> ~~~~
> (match-let (((input . output) (pipe)))
>    ;; Hack to work around Guile bug 52835 -- How does
>    ;; duplicating the port help? From the docs: "Returns a
>    ;; new port which is opened on a duplicate of the file
>    ;; descriptor underlying port, with mode string modes as
>    ;; for open-file. The two ports will share a file position
>    ;; and file status flags. [...]"
>    (define dup-output (duplicate-port output "w"))

The above Guile bug occurs because the current output and error ports
point to the same file descriptor.  Using duplicate-port makes sure that
we get a port with a duplicated file descriptor!

>    ;; Void pipe, but holds the pid for close-pipe.
>    (define dummy-pipe
>      ;; Set current-input-port to /dev/null. -- What will be
>      ;; read from there? Nothing?
>      (with-input-from-file "/dev/null"

Yes, for our use-case we don't need to feed anything to the command, but
it's always possible to hook this up to a pipe if you need to.

>        (lambda ()
>          ;; Set the current-output-port to the one created
>          ;; above using (pipe).
>          (with-output-to-port output
>            (lambda ()
>              ;; Set the error port to the duplicated output
>              ;; port. This might be the redirection of stderr
>              ;; to stdout.
>              (with-error-to-port dup-output

Exactly, this is the redirection.

>                (lambda ()
>                  ;; Run open-file*, but why is there an empty
>                  ;; string prepended to command? Perhaps to
>                  ;; allow using either a list or a string as
>                  ;; a command?
>                  (apply open-pipe* (cons "" command)))))))))

Here's the undefined behavior, the first argument of open-pipe* is a
mode for the pipe it opens, but here we don't want it to open any pipes,
all our default ports are setup so that start_child will set the child's
stdin/out/err to their file descriptors.

>    (close-port output)
>    (close-port dup-output)
>    (handler input)
>    (close-port input)
>    (close-pipe dummy-pipe))
> ~~~~
>
> My other question is: Do I still need this workaround, if I use the following, 
> to run commands? And if so, why? In which cases would my code not do the right 
> thing? (reference: 
> https://notabug.org/ZelphirKaltstahl/guile-examples/src/2dead9f7bb9b40fc26eb490a93e1dc7abca7252c/shell/example-03-using-popen-get-out-and-error.scm):

Looking briefly at your code, I don't think that bug could be affecting
you.  You can have an issue if you're trying to redirect a standard fd
to another standard fd, but if you're using fresh ports it should be ok.

Best,
-- 
Josselin Poiret



  reply	other threads:[~2022-03-09 14:14 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-22  9:29 Shell commands with output to string Zelphir Kaltstahl
2022-02-22  9:38 ` Zelphir Kaltstahl
2022-02-22 10:20   ` Alex Sassmannshausen
2022-02-22 10:43     ` post
2022-02-23 14:01       ` Josselin Poiret
2022-03-08 23:12         ` Zelphir Kaltstahl
2022-03-09 14:14           ` Josselin Poiret [this message]
2022-02-22 11:20     ` Neil Jerram
2022-02-23  1:28       ` Zelphir Kaltstahl
2022-02-23  1:29     ` Zelphir Kaltstahl
2022-02-22 10:21   ` tomas
2022-02-22 14:27 ` Olivier Dion via General Guile related discussions
2022-02-22 16:00   ` Leo Butler
2022-02-22 16:33     ` Olivier Dion via General Guile related discussions
2022-02-23  1:26       ` Zelphir Kaltstahl
2022-02-23 14:13         ` Olivier Dion via General Guile related discussions
2022-02-26  0:32           ` Zelphir Kaltstahl
  -- strict thread matches above, loose matches on Subject: below --
2022-02-23 17:48 Blake Shaw
2022-02-23 18:25 ` Olivier Dion via General Guile related discussions

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=87r17bmcw2.fsf@jpoiret.xyz \
    --to=dev@jpoiret.xyz \
    --cc=guile-user@gnu.org \
    --cc=zelphirkaltstahl@posteo.de \
    /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).