Ian Lynagh | 28 Apr 15:36 2013

Proposal: When possible, give more useful exceptions from rawSystem and friends


Hi all,

Currently, if you try to use rawSystem to run a program that doesn't
exist, you will just get a bad error code as a result, e.g. this
program:

    import System.IO.Error
    import System.Process

    main :: IO ()
    main = do (rawSystem "/bin/true" [] >>= print)
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              (rawSystem "/bin/false" [] >>= print)
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              (rawSystem "/non/existent" [] >>= print) 
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              putStrLn "Done"

prints:

    ExitSuccess
    ExitFailure 1
    ExitFailure 127
    Done

However, if we are on a platform that supports vfork, then we can pass
information from the child process back to the parent process as they
share address space. With the attached patch we instead get:

(Continue reading)

Ben Millwood | 28 Apr 21:30 2013
Picon

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends

On Sun, Apr 28, 2013 at 02:36:24PM +0100, Ian Lynagh wrote:
>However, if we are on a platform that supports vfork, then we can pass
>information from the child process back to the parent process as they
>share address space.

AIUI the POSIX standard at least does not guarantee this behaviour – 
it's perfectly OK in theory for vfork to be equal to fork, and more 
generally the behaviour of a vfork which edits its parent's memory is 
seemingly unspecified. I don't know if Linux provides more guarantees 
than that, but if we're relying on nonstandard behaviour this fact 
should be at least commented.

I think the "right" way to do this is creating a pipe() beforehand and 
then using conventional-fork, and writing to the pipe if anything goes 
wrong. I'm not an expert though!

-- Ben

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Ian Lynagh | 7 May 12:18 2013

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends

On Sun, Apr 28, 2013 at 08:30:19PM +0100, Ben Millwood wrote:
> On Sun, Apr 28, 2013 at 02:36:24PM +0100, Ian Lynagh wrote:
> >However, if we are on a platform that supports vfork, then we can pass
> >information from the child process back to the parent process as they
> >share address space.
> 
> AIUI the POSIX standard at least does not guarantee this behaviour –
> it's perfectly OK in theory for vfork to be equal to fork, and more
> generally the behaviour of a vfork which edits its parent's memory
> is seemingly unspecified. I don't know if Linux provides more
> guarantees than that, but if we're relying on nonstandard behaviour
> this fact should be at least commented.

We don't actually rely on it: If it doesn't work then programs just get
less helpful error messages. But we'd still like it to work as often as
possible.

> I think the "right" way to do this is creating a pipe() beforehand
> and then using conventional-fork, and writing to the pipe if
> anything goes wrong.

Aha, thanks. I'll look into this.

Thanks
Ian
--

-- 
Ian Lynagh, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com/

_______________________________________________
(Continue reading)

Ian Lynagh | 2 Jun 23:25 2013

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends

On Sun, Apr 28, 2013 at 08:30:19PM +0100, Ben Millwood wrote:
> On Sun, Apr 28, 2013 at 02:36:24PM +0100, Ian Lynagh wrote:
> >However, if we are on a platform that supports vfork, then we can pass
> >information from the child process back to the parent process as they
> >share address space.
> 
> I think the "right" way to do this is creating a pipe() beforehand

I've just pushed patches to do it this way.

Thanks
Ian
--

-- 
Ian Lynagh, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com/
Niklas Hambüchen | 29 Apr 02:23 2013

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends

Hello Ian,

does your patch only apply to rawSystem or would it also improve
scenarios with createProcess involved like the following?

http://www.haskell.org/pipermail/haskell-cafe/2012-August/102824.html

Thanks!
Ian Lynagh | 7 May 12:16 2013

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends


Hi Niklas,

On Mon, Apr 29, 2013 at 08:23:52AM +0800, Niklas Hambüchen wrote:
> 
> does your patch only apply to rawSystem or would it also improve
> scenarios with createProcess involved like the following?
> 
> http://www.haskell.org/pipermail/haskell-cafe/2012-August/102824.html

It would work for createProcess too (well, you actually get the error
when you waitForProcess on the ProcessHandle that createProcess
returns).

Thanks
Ian
--

-- 
Ian Lynagh, Haskell Consultant
Well-Typed LLP, http://www.well-typed.com/
Evan Laforge | 29 Apr 04:50 2013
Picon

Re: Proposal: When possible, give more useful exceptions from rawSystem and friends

I definitely support better errors for binary not found, I have always used a wrapper that waits for the child and logs an error if it was not found, but all it does is print a msg to stderr.

I still feel like we should learn from the latest python subprocess.py module.  They have fixed a number of subtle bugs over many years and much testing.  They also use pipes to communicate errors back to the parent.

That said, I'm in favor of this patch because it's still better than the current situation.


On Sun, Apr 28, 2013 at 7:06 PM, Ian Lynagh <ian <at> well-typed.com> wrote:

Hi all,

Currently, if you try to use rawSystem to run a program that doesn't
exist, you will just get a bad error code as a result, e.g. this
program:

    import System.IO.Error
    import System.Process

    main :: IO ()
    main = do (rawSystem "/bin/true" [] >>= print)
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              (rawSystem "/bin/false" [] >>= print)
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              (rawSystem "/non/existent" [] >>= print)
                `catchIOError` \e -> putStrLn ("Exc: " ++ show e)
              putStrLn "Done"

prints:

    ExitSuccess
    ExitFailure 1
    ExitFailure 127
    Done

However, if we are on a platform that supports vfork, then we can pass
information from the child process back to the parent process as they
share address space. With the attached patch we instead get:

    ExitSuccess
    ExitFailure 1
    Exc: resolveProcessHandle: does not exist (No such file or directory)

(and it should be easy to also get "/non/existent" in the exception).


If there are platforms that don't support vfork, then they will still
give the old output. I haven't yet looked at whether we can also get
good exceptions on Windows (the patch won't build on Windows yet; I
still need to update the Windows-specific code).

I think that despite the possibility that some platforms may not be able
to support it, we should provide the better behaviour on platforms that
do.

What do you think?
And do you have any other comments on the patch?

(this proposal was inspired by
http://hackage.haskell.org/trac/ghc/ticket/7859).


Suggested discussion deadline: Mon 13 May 2013.


Thanks
Ian


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries

Gmane