unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* What is the output port of `system*'?
@ 2014-04-26 19:55 Diogo F. S. Ramos
  2014-04-26 22:37 ` Taylan Ulrich Bayirli/Kammer
  0 siblings, 1 reply; 5+ messages in thread
From: Diogo F. S. Ramos @ 2014-04-26 19:55 UTC (permalink / raw)
  To: guile-user

The following program doesn't output to a string, which I expected.

--8<---------------cut here---------------start------------->8---
(define foo
  (with-output-to-string
    (lambda ()
      (system* "ls" "/tmp"))))
--8<---------------cut here---------------end--------------->8---



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

* Re: What is the output port of `system*'?
  2014-04-26 19:55 What is the output port of `system*'? Diogo F. S. Ramos
@ 2014-04-26 22:37 ` Taylan Ulrich Bayirli/Kammer
  2014-04-27  5:30   ` Diogo F. S. Ramos
  0 siblings, 1 reply; 5+ messages in thread
From: Taylan Ulrich Bayirli/Kammer @ 2014-04-26 22:37 UTC (permalink / raw)
  To: Diogo F. S. Ramos; +Cc: guile-user

"Diogo F. S. Ramos" <dfsr@riseup.net> writes:

> The following program doesn't output to a string, which I expected.
>
> (define foo
>   (with-output-to-string
>     (lambda ()
>       (system* "ls" "/tmp"))))

As the manual says about `system*':
> The command is executed using fork and execlp.

That implies certain restrictions.  See (ice-9 popen), documented in
(info "(guile) Pipes").  That also spawns a process but sets its stdout
to a Unix pipe for which it gives you a Guile port, from which you can
drain the output to construct a string.

(Details: `with-output-to-string' could be said to work by setting the
current output port to some special value (a "string port" I guess) that
tells the deepest Guile IO procedures to construct a string instead of
writing to a file descriptor; when you spawn a separate process you
obviously lose this ability, the spawned process simply inherits the
current stdout file descriptor of the Guile process and writes to that.)

By the way, you might be better off doing things directly within Guile
instead of spawning external processes and trying to use their output.
In case you really wanted to do something with the output of ls(1), you
might want to use (ice-9 ftw) instead, but I suppose it was just an
example.

Taylan



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

* Re: What is the output port of `system*'?
  2014-04-26 22:37 ` Taylan Ulrich Bayirli/Kammer
@ 2014-04-27  5:30   ` Diogo F. S. Ramos
  2014-04-27  6:09     ` Mark H Weaver
  0 siblings, 1 reply; 5+ messages in thread
From: Diogo F. S. Ramos @ 2014-04-27  5:30 UTC (permalink / raw)
  To: Taylan Ulrich Bayirli/Kammer; +Cc: guile-user

> "Diogo F. S. Ramos" <dfsr@riseup.net> writes:
>
>> The following program doesn't output to a string, which I expected.
>>
>> (define foo
>>   (with-output-to-string
>>     (lambda ()
>>       (system* "ls" "/tmp"))))
>
> As the manual says about `system*':
>> The command is executed using fork and execlp.
>
> That implies certain restrictions.  See (ice-9 popen), documented in
> (info "(guile) Pipes").  That also spawns a process but sets its stdout
> to a Unix pipe for which it gives you a Guile port, from which you can
> drain the output to construct a string.

Thanks for the pipe reference.

Indeed, something can probably be written with these pipes to achieve
what my sample program tried to do tho the higher issue remains.

> (Details: `with-output-to-string' could be said to work by setting the
> current output port to some special value (a "string port" I guess) that
> tells the deepest Guile IO procedures to construct a string instead of
> writing to a file descriptor; when you spawn a separate process you
> obviously lose this ability, the spawned process simply inherits the
> current stdout file descriptor of the Guile process and writes to that.)

I'm not sure about the underlying implementation, but I expected all
output to (current-output-port) going to the resulting string, hence my
question.

As an example of this behavior, I point to the following Racket program:

--8<---------------cut here---------------start------------->8---
#lang racket

(define foo
  (with-output-to-string
    (lambda ()
      (system* (find-executable-path "ls") "/tmp"))))
--8<---------------cut here---------------end--------------->8---



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

* Re: What is the output port of `system*'?
  2014-04-27  5:30   ` Diogo F. S. Ramos
@ 2014-04-27  6:09     ` Mark H Weaver
  2014-04-27 19:27       ` Diogo F. S. Ramos
  0 siblings, 1 reply; 5+ messages in thread
From: Mark H Weaver @ 2014-04-27  6:09 UTC (permalink / raw)
  To: Diogo F. S. Ramos; +Cc: guile-user

"Diogo F. S. Ramos" <dfsr@riseup.net> writes:

>> "Diogo F. S. Ramos" <dfsr@riseup.net> writes:
>>
>>> The following program doesn't output to a string, which I expected.
>>>
>>> (define foo
>>>   (with-output-to-string
>>>     (lambda ()
>>>       (system* "ls" "/tmp"))))
>>
>> As the manual says about `system*':
>>> The command is executed using fork and execlp.
>>
>> That implies certain restrictions.  See (ice-9 popen), documented in
>> (info "(guile) Pipes").  That also spawns a process but sets its stdout
>> to a Unix pipe for which it gives you a Guile port, from which you can
>> drain the output to construct a string.
>
> Thanks for the pipe reference.
>
> Indeed, something can probably be written with these pipes to achieve
> what my sample program tried to do tho the higher issue remains.
>
>> (Details: `with-output-to-string' could be said to work by setting the
>> current output port to some special value (a "string port" I guess) that
>> tells the deepest Guile IO procedures to construct a string instead of
>> writing to a file descriptor; when you spawn a separate process you
>> obviously lose this ability, the spawned process simply inherits the
>> current stdout file descriptor of the Guile process and writes to that.)
>
> I'm not sure about the underlying implementation, but I expected all
> output to (current-output-port) going to the resulting string, hence my
> question.

All output to (current-output-port) _does_ go into the resulting string.
However, when you launch a subprocess using 'system*', the output of
that process does _not_ go to (current-output-port).  Instead, it goes
to POSIX file descriptor 1, which is left unchanged by the Scheme
constructs that change (current-output-port).  Ditto for
(current-input-port) and (current-error-port).  There are at least two
reasons for this:

* POSIX file descriptors cannot represent all of the types of ports
  supported by Guile, such as string ports and custom binary ports.

* The current-output-port is a fluid variable, which among other things
  is thread-local.  Obviously, POSIX file descriptors are per-process.

> As an example of this behavior, I point to the following Racket program:
>
> #lang racket
>
> (define foo
>   (with-output-to-string
>     (lambda ()
>       (system* (find-executable-path "ls") "/tmp"))))

I agree that it would be nice to make this work as you expected.  In
order to handle ports that are not simply raw POSIX file descriptors
(e.g. string ports), we'd need to create a pipe behind the scenes, and
arrange for thread(s) in the current process to copy data between the
pipe(s) and the Scheme port.

I'd like to do this at some point, although for the sake of backward
compatibility we'd probably have to leave 'system' and 'system*' as-is
and create a new API that works more intuitively.

      Mark



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

* Re: What is the output port of `system*'?
  2014-04-27  6:09     ` Mark H Weaver
@ 2014-04-27 19:27       ` Diogo F. S. Ramos
  0 siblings, 0 replies; 5+ messages in thread
From: Diogo F. S. Ramos @ 2014-04-27 19:27 UTC (permalink / raw)
  To: Mark H Weaver; +Cc: guile-user

>> As an example of this behavior, I point to the following Racket program:
>>
>> #lang racket
>>
>> (define foo
>>   (with-output-to-string
>>     (lambda ()
>>       (system* (find-executable-path "ls") "/tmp"))))
>
> I agree that it would be nice to make this work as you expected.  In
> order to handle ports that are not simply raw POSIX file descriptors
> (e.g. string ports), we'd need to create a pipe behind the scenes, and
> arrange for thread(s) in the current process to copy data between the
> pipe(s) and the Scheme port.
>
> I'd like to do this at some point, although for the sake of backward
> compatibility we'd probably have to leave 'system' and 'system*' as-is
> and create a new API that works more intuitively.

If you do, may I suggest taking a look at Racket's Processes?

I'm not aware of things like "custodian" or "synchromizable event" in
Guile, but I've used Racket's Processes successfully in the past.



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

end of thread, other threads:[~2014-04-27 19:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-26 19:55 What is the output port of `system*'? Diogo F. S. Ramos
2014-04-26 22:37 ` Taylan Ulrich Bayirli/Kammer
2014-04-27  5:30   ` Diogo F. S. Ramos
2014-04-27  6:09     ` Mark H Weaver
2014-04-27 19:27       ` Diogo F. S. Ramos

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).