unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Support for (system '("echo" "foo" "bar"))
@ 2003-10-28 21:15 Rob Browning
  2003-10-28 22:13 ` Paul Jarc
                   ` (2 more replies)
  0 siblings, 3 replies; 34+ messages in thread
From: Rob Browning @ 2003-10-28 21:15 UTC (permalink / raw)



I've just finished adding support for calling (system cmd) with a list
argument.  This causes it to use fork/execlp/waitpid nstead of calling
underlying OS's system() function.  This should be safer in cases
where it's acceptable because it avoids /bin/sh interpretation and the
attendant risks like sneaky IFS settings, unexpected expansions, etc.

This idea was borrowed from perl, and seems fairly useful, but I
wanted to see if there were any substantial objections before I
commit.  I suppose if this addition is acceptable, I should probably
also see about doing something similar to open-*-pipe.

Also, if people don't like this approach, perhaps there's some
alternate (and more suitable) way to accomplish something similar,
i.e. making it easy to more safely execute a sub-process when you
don't need shell interpolation.

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-28 21:15 Support for (system '("echo" "foo" "bar")) Rob Browning
@ 2003-10-28 22:13 ` Paul Jarc
  2003-10-29  7:58 ` tomas
  2003-10-29 13:58 ` Greg Troxel
  2 siblings, 0 replies; 34+ messages in thread
From: Paul Jarc @ 2003-10-28 22:13 UTC (permalink / raw)


Rob Browning <rlb@defaultvalue.org> wrote:
> I've just finished adding support for calling (system cmd) with a list
> argument.

That would certainly be useful.  FWIW, I have a set of related
functions in run.scm in my prjlibs package:
<URL:http://multivac.cwru.edu./prjlibs/>


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-28 21:15 Support for (system '("echo" "foo" "bar")) Rob Browning
  2003-10-28 22:13 ` Paul Jarc
@ 2003-10-29  7:58 ` tomas
  2003-10-29 13:58 ` Greg Troxel
  2 siblings, 0 replies; 34+ messages in thread
From: tomas @ 2003-10-29  7:58 UTC (permalink / raw)
  Cc: guile-devel

On Tue, Oct 28, 2003 at 03:15:26PM -0600, Rob Browning wrote:
> 
> I've just finished adding support for calling (system cmd) with a list
[...]
> This idea was borrowed from perl, [...]

If I get you right, you duplicate Perl's magic: when the arg is
a singleton, use system() (with all the shell implications), when
it's a list use execlp etc.

While I have no issues with that (on the contrary, I think those
things are quite handy in a scripting tool!), it ``sticks out''
a bit in Scheme. I'd expect `system' to be system(), and a function
by another name to do the magic you describe. Why not system* or
somesuch? (doing the single-element/several-element magic).

If I got you right, that is.

Regards
-- tomas


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-28 21:15 Support for (system '("echo" "foo" "bar")) Rob Browning
  2003-10-28 22:13 ` Paul Jarc
  2003-10-29  7:58 ` tomas
@ 2003-10-29 13:58 ` Greg Troxel
  2003-10-29 14:04   ` Rob Browning
  2003-10-30 20:09   ` Kevin Ryde
  2 siblings, 2 replies; 34+ messages in thread
From: Greg Troxel @ 2003-10-29 13:58 UTC (permalink / raw)
  Cc: guile-devel

This violates the Principle of Least Astonishment.  In guile we have a
lot of procedures that are essentially just the 'obvious'
scheme-wrapped versions of system calls and libc functions.

system(3) (on NetBSD, which claimes conformance with ANSI X3.159-1989
(``ANSI C'') and IEEE Std 1003.2-1992 (``POSIX.2'')), is specified to
use sh(1).

POLA to me says that system with a list of strings would append them
with spaces and then behave as if it had been called with that single
string.  This means /bin/sh, with globbing, file redirection, and
multiple commands, not the simpler exec treatment.

That said, a procedure to encapsulate the safer fork/exec/wait process
would be very nice.

So IMHO another name is warranted, and system* as already suggested
seems good, since it hints that it isn't really system(3), but
something else that is similar.

Also, it might be nice to have environments with system* but not
system (as a kind of 'safe environment').  A good case can be made
that system(3) should not be used, except perhaps with constant
strings - certainly not with unchecked user input.

Is it important/useful to you to have the extended functionality have
the same name?

-- 
        Greg Troxel <gdt@ir.bbn.com>


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 13:58 ` Greg Troxel
@ 2003-10-29 14:04   ` Rob Browning
  2003-10-29 16:15     ` Marius Vollmer
  2003-10-30 20:09   ` Kevin Ryde
  1 sibling, 1 reply; 34+ messages in thread
From: Rob Browning @ 2003-10-29 14:04 UTC (permalink / raw)
  Cc: guile-devel

Greg Troxel <gdt@ir.bbn.com> writes:

> Is it important/useful to you to have the extended functionality have
> the same name?

Nope, system* would be perfectly fine with me too.

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 14:04   ` Rob Browning
@ 2003-10-29 16:15     ` Marius Vollmer
  2003-10-29 18:13       ` Rob Browning
  0 siblings, 1 reply; 34+ messages in thread
From: Marius Vollmer @ 2003-10-29 16:15 UTC (permalink / raw)
  Cc: guile-devel, Greg Troxel

Rob Browning <rlb@defaultvalue.org> writes:

> Nope, system* would be perfectly fine with me too.

That's what I prefer as well.

-- 
GPG: D5D4E405 - 2F9B BCCC 8527 692A 04E3  331E FAF8 226A D5D4 E405


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 16:15     ` Marius Vollmer
@ 2003-10-29 18:13       ` Rob Browning
  2003-10-29 22:32         ` Paul Jarc
  2003-10-30  1:41         ` Alex Shinn
  0 siblings, 2 replies; 34+ messages in thread
From: Rob Browning @ 2003-10-29 18:13 UTC (permalink / raw)
  Cc: guile-devel, Greg Troxel

Marius Vollmer <mvo@zagadka.de> writes:

>> Nope, system* would be perfectly fine with me too.
>
> That's what I prefer as well.

So would we want (system* . args) or (system* arg-list)?

What are guile's argument count limitations?  (Suppose the underlying
OS's could be relevant as well...)

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 18:13       ` Rob Browning
@ 2003-10-29 22:32         ` Paul Jarc
  2003-10-30  1:41         ` Alex Shinn
  1 sibling, 0 replies; 34+ messages in thread
From: Paul Jarc @ 2003-10-29 22:32 UTC (permalink / raw)
  Cc: guile-devel, Marius Vollmer, Greg Troxel

Rob Browning <rlb@defaultvalue.org> wrote:
> So would we want (system* . args) or (system* arg-list)?

I like (system* arg-list).

> What are guile's argument count limitations?  (Suppose the underlying
> OS's could be relevant as well...)

If the caller exceeds the OS limit, execve will fail, and we'll get a
system-error exception, won't we?  Or is that not what you're talking
about?


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 18:13       ` Rob Browning
  2003-10-29 22:32         ` Paul Jarc
@ 2003-10-30  1:41         ` Alex Shinn
  2003-10-30 10:31           ` tomas
  1 sibling, 1 reply; 34+ messages in thread
From: Alex Shinn @ 2003-10-30  1:41 UTC (permalink / raw)


At Wed, 29 Oct 2003 12:13:11 -0600, Rob Browning wrote:
> 
> Marius Vollmer <mvo@zagadka.de> writes:
> 
> >> Nope, system* would be perfectly fine with me too.
> >
> > That's what I prefer as well.
> 
> So would we want (system* . args) or (system* arg-list)?

FWIW, MzScheme made the same choice of the name system* and uses
(system* . args)

Chicken uses (system* fmt . args) => (system (apply format fmt args))

-- 
Alex


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-30  1:41         ` Alex Shinn
@ 2003-10-30 10:31           ` tomas
  0 siblings, 0 replies; 34+ messages in thread
From: tomas @ 2003-10-30 10:31 UTC (permalink / raw)
  Cc: guile-devel

On Thu, Oct 30, 2003 at 10:41:05AM +0900, Alex Shinn wrote:
> At Wed, 29 Oct 2003 12:13:11 -0600, Rob Browning wrote:
> > 
> > Marius Vollmer <mvo@zagadka.de> writes:
> > 
> > >> Nope, system* would be perfectly fine with me too.
> > >
> > > That's what I prefer as well.
> > 
> > So would we want (system* . args) or (system* arg-list)?
> 
> FWIW, MzScheme made the same choice of the name system* and uses
> (system* . args)
> 
> Chicken uses (system* fmt . args) => (system (apply format fmt args))

I'd prefer (systems . args) too, but I've stirred up enough already ;-)

Cheers
-- tomas


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-29 13:58 ` Greg Troxel
  2003-10-29 14:04   ` Rob Browning
@ 2003-10-30 20:09   ` Kevin Ryde
  2003-10-31  5:51     ` Rob Browning
  1 sibling, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-30 20:09 UTC (permalink / raw)


Greg Troxel <gdt@ir.bbn.com> writes:
>
> That said, a procedure to encapsulate the safer fork/exec/wait process
> would be very nice.

If it does a fork and exec then it could be called fork-exec :).

The old DOS systems used to use "spawn" for that sort of thing I think
(spawnl, spawnle, etc like the exec functions).

Either way, if it can get the errno back to the parent when exec fails
(and use _exit) then it'd be a nice improvement over a fork and exec
one might write explicitly.  (A close-on-exec pipe is a good way to do
that.)


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-30 20:09   ` Kevin Ryde
@ 2003-10-31  5:51     ` Rob Browning
  2003-10-31 17:05       ` Paul Jarc
  2003-10-31 20:19       ` Kevin Ryde
  0 siblings, 2 replies; 34+ messages in thread
From: Rob Browning @ 2003-10-31  5:51 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> writes:

> If it does a fork and exec then it could be called fork-exec :).
>
> The old DOS systems used to use "spawn" for that sort of thing I think
> (spawnl, spawnle, etc like the exec functions).
>
> Either way, if it can get the errno back to the parent when exec fails
> (and use _exit) then it'd be a nice improvement over a fork and exec
> one might write explicitly.  (A close-on-exec pipe is a good way to do
> that.)

Right now I just have this first (quick) pass at (system* . args),
which should provide access to errno via scm_execlp:

{
  if (SCM_NULLP (cmds))
    SCM_WRONG_TYPE_ARG (1, cmds);

  if (SCM_CONSP (cmds))
    {
      // better be a list of strings, and we call exec.
      int pid = fork ();
      if (pid == -1)
        SCM_SYSERROR;
      else if (pid)
        {
          int wait_result;
          int status;
          SCM_SYSCALL (wait_result = waitpid (pid, &status, 0));
          if (wait_result == -1) SCM_SYSERROR;
          return SCM_MAKINUM (0L + status);
        }
      else
        {
          scm_execlp (SCM_CAR(cmds), cmds);
          SCM_SYSERROR;
          /* not reached.  */
          return SCM_BOOL_F;
        }
    }
  else
    SCM_WRONG_TYPE_ARG (1, SCM_CAR (cmds));
}


-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31  5:51     ` Rob Browning
@ 2003-10-31 17:05       ` Paul Jarc
  2003-10-31 17:47         ` Rob Browning
  2003-10-31 20:19       ` Kevin Ryde
  1 sibling, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 17:05 UTC (permalink / raw)
  Cc: guile-devel

Rob Browning <rlb@defaultvalue.org> wrote:
> {
>   if (SCM_NULLP (cmds))
>     SCM_WRONG_TYPE_ARG (1, cmds);
>
>   if (SCM_CONSP (cmds))
...
>   else
>     SCM_WRONG_TYPE_ARG (1, SCM_CAR (cmds));

This doesn't look right - you're looking at (car cmds) when cmds is
not a cons.  How about:
{
  if (! SCM_CONSP (cmds))
    SCM_WRONG_TYPE_ARG (1, cmds);
  ...
}

That should catch the null case too.  Or, to get the behavior Kevin
described:

(define (system* . args)
  (flush-all-ports)
  (let* ((p (pipe))
         (pid (primitive-fork)))
    (if (zero? pid)
      (catch
       'system-error
       (lambda ()
         (close-port (car p))
         (fcntl (cdr p) F_SETFD FD_CLOEXEC)
         (apply execlp (car args) args))
       (lambda . exception
         (write exception (cdr p))
         (force-output (cdr p))
         (primitive-exit)))
      (begin
        (close-port (cdr p))
        (let* ((exception (read (car p)))
               (status (cdr (waitpid pid))))
          (close-port (car p))
          (if (not (eof-object? exception))
            (apply throw exception)
            status))))))


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 17:05       ` Paul Jarc
@ 2003-10-31 17:47         ` Rob Browning
  2003-10-31 17:59           ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Rob Browning @ 2003-10-31 17:47 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:

>>     SCM_WRONG_TYPE_ARG (1, SCM_CAR (cmds));

Oh, right.  Good catch, that's a typo left over from a previous
incarnation.

> That should catch the null case too.  Or, to get the behavior Kevin
> described:

Hmm, maybe that's better.

>        (lambda . exception
>          (write exception (cdr p))
>          (force-output (cdr p))
>          (primitive-exit)))

Looks like maybe that should be (lambda exception ...).

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 17:47         ` Rob Browning
@ 2003-10-31 17:59           ` Paul Jarc
  2003-10-31 20:15             ` Kevin Ryde
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 17:59 UTC (permalink / raw)
  Cc: guile-devel

Rob Browning <rlb@defaultvalue.org> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>>        (lambda . exception
>>          (write exception (cdr p))
>>          (force-output (cdr p))
>>          (primitive-exit)))
>
> Looks like maybe that should be (lambda exception ...).

Oops, right.  Kevin also mentioned using _exit.  I'm not sure why that
would be important, but if it is, then we'd also need a
primitive-_exit Scheme binding.


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 17:59           ` Paul Jarc
@ 2003-10-31 20:15             ` Kevin Ryde
  2003-10-31 20:31               ` Paul Jarc
  2003-10-31 22:49               ` Jonathan Bartlett
  0 siblings, 2 replies; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 20:15 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> Oops, right.  Kevin also mentioned using _exit.  I'm not sure why that
> would be important,

When exiting due to an exec failure, you generally don't want to run
atexit handlers or flush stdio buffers.  Those things of course are
not done if the exec succeeds.

In particular in guile-gtk the gtk atexit handlers do some shutdowns
on the X connection, rendering it unusable back in the parent.

> but if it is, then we'd also need a primitive-_exit Scheme binding.

There was a bug report requesting that, or that primitive-exit change
to be _exit anyway.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31  5:51     ` Rob Browning
  2003-10-31 17:05       ` Paul Jarc
@ 2003-10-31 20:19       ` Kevin Ryde
  2003-10-31 20:37         ` Paul Jarc
  1 sibling, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 20:19 UTC (permalink / raw)


Rob Browning <rlb@defaultvalue.org> writes:
>
>           SCM_SYSCALL (wait_result = waitpid (pid, &status, 0));

As a suggestion, I think a variation that just returned the child pid
would be nice (or threw an execption for an exec failure).


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 20:15             ` Kevin Ryde
@ 2003-10-31 20:31               ` Paul Jarc
  2003-10-31 21:00                 ` Kevin Ryde
  2003-10-31 22:49               ` Jonathan Bartlett
  1 sibling, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 20:31 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>> Oops, right.  Kevin also mentioned using _exit.  I'm not sure why that
>> would be important,
>
> When exiting due to an exec failure, you generally don't want to run
> atexit handlers or flush stdio buffers.  Those things of course are
> not done if the exec succeeds.

Ok.  My procedure uses flush-all-ports before the fork, but atexit
could still be an issue.  In this particular case, though, we don't
need _exit; we can just do (raise SIGKILL).  The parent ignores the
exit status if an exception was passed back.


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 20:19       ` Kevin Ryde
@ 2003-10-31 20:37         ` Paul Jarc
  2003-10-31 21:02           ` Rob Browning
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 20:37 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> As a suggestion, I think a variation that just returned the child pid
> would be nice (or threw an execption for an exec failure).

(define (system*/nowait . args)
  (flush-all-ports)
  (let* ((p (pipe))
         (pid (primitive-fork)))
    (if (zero? pid)
      (catch
       'system-error
       (lambda ()
         (close-port (car p))
         (fcntl (cdr p) F_SETFD FD_CLOEXEC)
         (apply execlp (car args) args))
       (lambda exception
         (write exception (cdr p))
         (force-output (cdr p))
         (raise SIGKILL)))
      (begin
        (close-port (cdr p))
        (let ((exception (read (car p))))
          (close-port (car p))
          (if (not (eof-object? exception))
            (apply throw exception)
            pid))))))

I'd still prefer the argv list as a single Scheme argument, though,
since it saves an "apply" when the list is dynamically constructed.


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 20:31               ` Paul Jarc
@ 2003-10-31 21:00                 ` Kevin Ryde
  2003-10-31 21:18                   ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 21:00 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> My procedure uses flush-all-ports before the fork,

The current "system" function doesn't do that does it?  Might want to
omit it from this arglist style too.

There shouldn't be a need to flush, provided the code in the child
is nice and tight and won't accidentally do so there.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 20:37         ` Paul Jarc
@ 2003-10-31 21:02           ` Rob Browning
  0 siblings, 0 replies; 34+ messages in thread
From: Rob Browning @ 2003-10-31 21:02 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:

> I'd still prefer the argv list as a single Scheme argument, though,
> since it saves an "apply" when the list is dynamically constructed.

Might well be too ugly, but we *could* have it accept either format.

-- 
Rob Browning
rlb @defaultvalue.org and @debian.org; previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 21:00                 ` Kevin Ryde
@ 2003-10-31 21:18                   ` Paul Jarc
  2003-10-31 21:48                     ` Kevin Ryde
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 21:18 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>> My procedure uses flush-all-ports before the fork,
>
> The current "system" function doesn't do that does it?

No.  Maybe it should.

> There shouldn't be a need to flush, provided the code in the child
> is nice and tight and won't accidentally do so there.

Suppose we write some data to a port, and then we lose all references
to the port without having closed it.  In this case, garbage
collection will free the port, which means closing it, which means,
flushing it.  Is it possible to guarantee that the child will not
trigger garbage collection?


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 21:18                   ` Paul Jarc
@ 2003-10-31 21:48                     ` Kevin Ryde
  2003-10-31 22:10                       ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 21:48 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> Is it possible to guarantee that the child will not trigger garbage
> collection?

Probably not.  A good reason to do it in C.  (Though it could be
argued that it ought to be possible to this sort of thing safely at
the scheme level, somehow.)

Incidentally, looking at glibc sysdeps/posix/system.c, it seems to
ignore SIGINT and SIGQUIT in the parent while running the child.  I'm
not up with the standards or conventions on this, but for maximum
compatibility I suppose a "system*" might like to do the same.

(A spawn-only variant probably wouldn't want to.)


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 21:48                     ` Kevin Ryde
@ 2003-10-31 22:10                       ` Paul Jarc
  2003-10-31 22:26                         ` Paul Jarc
  2003-10-31 22:50                         ` Kevin Ryde
  0 siblings, 2 replies; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 22:10 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>> Is it possible to guarantee that the child will not trigger garbage
>> collection?
>
> Probably not.  A good reason to do it in C.

Even in C, avoiding garbage collection is probably impossible.  At
some level, the child has to allocate the argv array that will be
passed to execve().

> (Though it could be argued that it ought to be possible to this sort
> of thing safely at the scheme level, somehow.)

I think my Scheme procedure is safe.

> Incidentally, looking at glibc sysdeps/posix/system.c, it seems to
> ignore SIGINT and SIGQUIT in the parent while running the child.  I'm
> not up with the standards or conventions on this, but for maximum
> compatibility I suppose a "system*" might like to do the same.

I believe that's geared toward applications running on a tty, with the
assumption that if the user interrupts the child, the parent is
supposed to keep running.  This may or may not be what an application
wants, so we should provide both varieties.  Given system*/nowait as
before, we can have (with whatever names):

(define (system*/no-ignore-signals . args)
  (cdr (waitpid (apply system*/nowait args))))
(define (system*/ignore-signals . args)
  (let* ((pid (apply system*/nowait args))
         (old-int  (sigaction SIGINT  SIG_IGN))
         (old-quit (sigaction SIGQUIT SIG_IGN))
         (status (cdr (waitpid (apply system*/nowait args)))))
    (sigaction SIGINT  (car old-int)  (cdr old-int))
    (sigaction SIGQUIT (car old-quit) (cdr old-quit))
    status))


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 22:10                       ` Paul Jarc
@ 2003-10-31 22:26                         ` Paul Jarc
  2003-10-31 22:42                           ` Kevin Ryde
  2003-10-31 22:50                         ` Kevin Ryde
  1 sibling, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 22:26 UTC (permalink / raw)


I wrote:
> (define (system*/ignore-signals . args)
>   (let* ((pid (apply system*/nowait args))
>          (old-int  (sigaction SIGINT  SIG_IGN))
>          (old-quit (sigaction SIGQUIT SIG_IGN))
>          (status (cdr (waitpid (apply system*/nowait args)))))
>     (sigaction SIGINT  (car old-int)  (cdr old-int))
>     (sigaction SIGQUIT (car old-quit) (cdr old-quit))
>     status))

Oops.  That should, of course, be:
(define (system*/ignore-signals . args)
  (let* ((pid (apply system*/nowait args))
         (old-int  (sigaction SIGINT  SIG_IGN))
         (old-quit (sigaction SIGQUIT SIG_IGN))
         (status (cdr (waitpid pid))))
    (sigaction SIGINT  (car old-int)  (cdr old-int))
    (sigaction SIGQUIT (car old-quit) (cdr old-quit))
    status))


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 22:26                         ` Paul Jarc
@ 2003-10-31 22:42                           ` Kevin Ryde
  0 siblings, 0 replies; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 22:42 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 455 bytes --]

prj@po.cwru.edu (Paul Jarc) writes:
>
>   (let* ((pid (apply system*/nowait args))
>          (old-int  (sigaction SIGINT  SIG_IGN))
>          (old-quit (sigaction SIGQUIT SIG_IGN))

In glibc the ignores are put on before the fork (and undone again in
the child).  Presumably to avoid a gap where the child is running but
the parent is not yet ignoring.

Oh, and SIGCHLD is blocked until after waitpid.

(Code below, for those who don't have it handy.)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: system.c --]
[-- Type: text/x-csrc, Size: 4152 bytes --]

/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/types.h>
#include <errno.h>


#ifndef	HAVE_GNU_LD
#define	__environ	environ
#endif

#define	SHELL_PATH	"/bin/sh"	/* Path of the shell.  */
#define	SHELL_NAME	"sh"		/* Name to give it.  */

/* Execute LINE as a shell command, returning its status.  */
int
__libc_system (const char *line)
{
  int status, save;
  pid_t pid;
  struct sigaction sa, intr, quit;
#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD
  sigset_t block, omask;
#endif

  if (line == NULL)
    /* Check that we have a command processor available.  It might
       not be available after a chroot(), for example.  */
    return __libc_system ("exit 0") == 0;

  sa.sa_handler = SIG_IGN;
  sa.sa_flags = 0;
  __sigemptyset (&sa.sa_mask);

  if (__sigaction (SIGINT, &sa, &intr) < 0)
    return -1;
  if (__sigaction (SIGQUIT, &sa, &quit) < 0)
    {
      save = errno;
      (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
      __set_errno (save);
      return -1;
    }

#ifndef WAITPID_CANNOT_BLOCK_SIGCHLD

/* SCO 3.2v4 has a bug where `waitpid' will never return if SIGCHLD is
   blocked.  This makes it impossible for `system' to be implemented in
   compliance with POSIX.2-1992.  They have acknowledged that this is a bug
   but I have not seen nor heard of any forthcoming fix.  */

  __sigemptyset (&block);
  __sigaddset (&block, SIGCHLD);
  save = errno;
  if (__sigprocmask (SIG_BLOCK, &block, &omask) < 0)
    {
      if (errno == ENOSYS)
	__set_errno (save);
      else
	{
	  save = errno;
	  (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
	  (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
	  __set_errno (save);
	  return -1;
	}
    }
# define UNBLOCK __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL)
#else
# define UNBLOCK 0
#endif

  pid = __fork ();
  if (pid == (pid_t) 0)
    {
      /* Child side.  */
      const char *new_argv[4];
      new_argv[0] = SHELL_NAME;
      new_argv[1] = "-c";
      new_argv[2] = line;
      new_argv[3] = NULL;

      /* Restore the signals.  */
      (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
      (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
      (void) UNBLOCK;

      /* Exec the shell.  */
      (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
      _exit (127);
    }
  else if (pid < (pid_t) 0)
    /* The fork failed.  */
    status = -1;
  else
    /* Parent side.  */
    {
#ifdef	NO_WAITPID
      pid_t child;
      do
	{
	  child = __wait (&status);
	  if (child <= -1 && errno != EINTR)
	    {
	      status = -1;
	      break;
	    }
	  /* Note that pid cannot be <= -1 and therefore the loop continues
	     when __wait returned with EINTR.  */
	}
      while (child != pid);
#else
      int n;

      do
	n = __waitpid (pid, &status, 0);
      while (n == -1 && errno == EINTR);

      if (n != pid)
	status = -1;
#endif
    }

  save = errno;
  if ((__sigaction (SIGINT, &intr, (struct sigaction *) NULL) |
       __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL) |
       UNBLOCK) != 0)
    {
      if (errno == ENOSYS)
	__set_errno (save);
      else
	return -1;
    }

  return status;
}
weak_alias (__libc_system, system)

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel

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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 20:15             ` Kevin Ryde
  2003-10-31 20:31               ` Paul Jarc
@ 2003-10-31 22:49               ` Jonathan Bartlett
  1 sibling, 0 replies; 34+ messages in thread
From: Jonathan Bartlett @ 2003-10-31 22:49 UTC (permalink / raw)
  Cc: guile-devel

> When exiting due to an exec failure, you generally don't want to run
> atexit handlers or flush stdio buffers.  Those things of course are
> not done if the exec succeeds.

This is true for many forks - you don't want the child cleaning up file
handles that are in use by the parent.   For example, closing connections
to databases et al.

Jon



_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 22:10                       ` Paul Jarc
  2003-10-31 22:26                         ` Paul Jarc
@ 2003-10-31 22:50                         ` Kevin Ryde
  2003-10-31 22:59                           ` Paul Jarc
  1 sibling, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 22:50 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> At some level, the child has to allocate the argv array that will be
> passed to execve().

Could do that in the parent, where any gc is certain to be safe.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 22:50                         ` Kevin Ryde
@ 2003-10-31 22:59                           ` Paul Jarc
  2003-10-31 23:25                             ` Kevin Ryde
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 22:59 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>> At some level, the child has to allocate the argv array that will be
>> passed to execve().
>
> Could do that in the parent, where any gc is certain to be safe.

True, but is it worth the effort?  What's the benefit supposed to be?
And how sure are we that nothing else could trigger garbage collection
(signal handlers, maybe)?


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 22:59                           ` Paul Jarc
@ 2003-10-31 23:25                             ` Kevin Ryde
  2003-10-31 23:34                               ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-10-31 23:25 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> True, but is it worth the effort?  What's the benefit supposed to be?

Only what you said about gc'ed port closing doing something the child
has no business touching.

> (signal handlers, maybe)

An ever present danger no doubt.  (They go via asyncs don't they?
Maybe call-with-blocked-asyncs around the fork.)

I guess some of these matters (if they're really problems) should be
outlined in the docs for primitive-fork.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 23:25                             ` Kevin Ryde
@ 2003-10-31 23:34                               ` Paul Jarc
  2003-11-02 21:13                                 ` Kevin Ryde
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-10-31 23:34 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> prj@po.cwru.edu (Paul Jarc) writes:
>> True, but is it worth the effort?  What's the benefit supposed to be?
>
> Only what you said about gc'ed port closing doing something the child
> has no business touching.

I claim that my Scheme version, which uses flush-all-ports before the
fork, and (raise SIGKILL) to terminate the child, does not suffer from
any problems of that sort.  Can you find any problems that it is
vulnerable to?  If not, what problem are we trying to solve by
rewriting it in C?


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-10-31 23:34                               ` Paul Jarc
@ 2003-11-02 21:13                                 ` Kevin Ryde
  2003-11-10 19:25                                   ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Kevin Ryde @ 2003-11-02 21:13 UTC (permalink / raw)


prj@po.cwru.edu (Paul Jarc) writes:
>
> I claim that my Scheme version, which uses flush-all-ports before the
> fork,

Oops, I was a bit slow on the uptake.  That flushes unreferenced ports
as well, of course.

You'll probably still want to block SIGCHLD though (when it exists),
the same as the main system() does.  I think that's to stop a slack
application handler possibly stealing the exit status, but I'm not too
well up on the subtleties of sigchld.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-11-02 21:13                                 ` Kevin Ryde
@ 2003-11-10 19:25                                   ` Paul Jarc
  2003-12-16 23:45                                     ` Paul Jarc
  0 siblings, 1 reply; 34+ messages in thread
From: Paul Jarc @ 2003-11-10 19:25 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> wrote:
> You'll probably still want to block SIGCHLD though (when it exists),
> the same as the main system() does.

That will require a Scheme binding for sigprocmask().  I'll give it a
go if no one beats me to it.

> I think that's to stop a slack application handler possibly stealing
> the exit status,

Sounds reasonable.


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

* Re: Support for (system '("echo" "foo" "bar"))
  2003-11-10 19:25                                   ` Paul Jarc
@ 2003-12-16 23:45                                     ` Paul Jarc
  0 siblings, 0 replies; 34+ messages in thread
From: Paul Jarc @ 2003-12-16 23:45 UTC (permalink / raw)


BTW, I've implemented the pass-the-error-back-to-the-parent thing in
my prjlibs package at <URL:http://multivac.cwru.edu./prjlibs/>.  (See
call/child/wait in run.scm.)  It's done in Scheme, and doesn't mess
with signals.  (I would like to mess with SIGCHLD, at least, but I'll
have to come up with a patch to add sigprocmask first.)


paul


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


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

end of thread, other threads:[~2003-12-16 23:45 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-10-28 21:15 Support for (system '("echo" "foo" "bar")) Rob Browning
2003-10-28 22:13 ` Paul Jarc
2003-10-29  7:58 ` tomas
2003-10-29 13:58 ` Greg Troxel
2003-10-29 14:04   ` Rob Browning
2003-10-29 16:15     ` Marius Vollmer
2003-10-29 18:13       ` Rob Browning
2003-10-29 22:32         ` Paul Jarc
2003-10-30  1:41         ` Alex Shinn
2003-10-30 10:31           ` tomas
2003-10-30 20:09   ` Kevin Ryde
2003-10-31  5:51     ` Rob Browning
2003-10-31 17:05       ` Paul Jarc
2003-10-31 17:47         ` Rob Browning
2003-10-31 17:59           ` Paul Jarc
2003-10-31 20:15             ` Kevin Ryde
2003-10-31 20:31               ` Paul Jarc
2003-10-31 21:00                 ` Kevin Ryde
2003-10-31 21:18                   ` Paul Jarc
2003-10-31 21:48                     ` Kevin Ryde
2003-10-31 22:10                       ` Paul Jarc
2003-10-31 22:26                         ` Paul Jarc
2003-10-31 22:42                           ` Kevin Ryde
2003-10-31 22:50                         ` Kevin Ryde
2003-10-31 22:59                           ` Paul Jarc
2003-10-31 23:25                             ` Kevin Ryde
2003-10-31 23:34                               ` Paul Jarc
2003-11-02 21:13                                 ` Kevin Ryde
2003-11-10 19:25                                   ` Paul Jarc
2003-12-16 23:45                                     ` Paul Jarc
2003-10-31 22:49               ` Jonathan Bartlett
2003-10-31 20:19       ` Kevin Ryde
2003-10-31 20:37         ` Paul Jarc
2003-10-31 21:02           ` Rob Browning

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