Thread overview
Opening temporary files for std.process.spawnProcess input/output
Feb 25, 2015
wobbles
Feb 25, 2015
Tobias Pankrath
Feb 25, 2015
Ali Çehreli
Feb 26, 2015
wobbles
February 25, 2015
Hi,
Any reason why the following wont work?

void main(string[] args)
{
    auto pidIn = File.tmpfile();
    auto pidOut = File.tmpfile();
    auto pid = spawnProcess(["ls", "./"], pidIn, pidOut, std.stdio.stdout, null, Config.newEnv);

    if(wait(pid) == 0)
        writefln("%s", pidOut.readln());
}

The pidOut.readln() throws this exception:
object.Exception@/usr/include/dmd/phobos/std/stdio.d(1377): Attempt to read from an unopened file.

I figured tmpfile() would be open for read/write by default?
Also, theres no way to pass in args to File.tmpfile() to make them read/write.

Any ideas?

February 25, 2015
On Wednesday, 25 February 2015 at 13:56:06 UTC, wobbles wrote:
> Hi,
> Any reason why the following wont work?
>
> void main(string[] args)
> {
>     auto pidIn = File.tmpfile();
>     auto pidOut = File.tmpfile();
>     auto pid = spawnProcess(["ls", "./"], pidIn, pidOut, std.stdio.stdout, null, Config.newEnv);
>
>     if(wait(pid) == 0)
>         writefln("%s", pidOut.readln());
> }
>
> The pidOut.readln() throws this exception:
> object.Exception@/usr/include/dmd/phobos/std/stdio.d(1377): Attempt to read from an unopened file.
>
> I figured tmpfile() would be open for read/write by default?
> Also, theres no way to pass in args to File.tmpfile() to make them read/write.
>
> Any ideas?

maybe only for writing: http://www.cplusplus.com/reference/cstdio/tmpfile/
February 25, 2015
On 02/25/2015 05:56 AM, wobbles wrote:

> Hi,
> Any reason why the following wont work?
>
> void main(string[] args)
> {
>      auto pidIn = File.tmpfile();
>      auto pidOut = File.tmpfile();
>      auto pid = spawnProcess(["ls", "./"], pidIn, pidOut,
> std.stdio.stdout, null, Config.newEnv);
>
>      if(wait(pid) == 0)
>          writefln("%s", pidOut.readln());
> }
>
> The pidOut.readln() throws this exception:
> object.Exception@/usr/include/dmd/phobos/std/stdio.d(1377): Attempt to
> read from an unopened file.
>
> I figured tmpfile() would be open for read/write by default?
> Also, theres no way to pass in args to File.tmpfile() to make them
> read/write.
>
> Any ideas?

It looks like the file is closed when spawnProcess is finished. I don't know whether it is done by spawnProcess explicitly or whether it is a behavior for temporary files.

How about using a pipe? The following works:

import std.stdio;
import std.process;

void main(string[] args)
{
    auto pidIn = File.tmpfile();
    auto pidOut = pipe();
    auto pid = spawnProcess(["ls", "./" ],
                            pidIn, pidOut.writeEnd,
                            std.stdio.stdout, null, Config.newEnv);

    if(wait(pid) == 0)
        writeln(pidOut.readEnd.byLine);
}

Ali

February 26, 2015
On Wednesday, 25 February 2015 at 19:09:16 UTC, Ali Çehreli wrote:
> On 02/25/2015 05:56 AM, wobbles wrote:
>
> > Hi,
> > Any reason why the following wont work?
> >
> > void main(string[] args)
> > {
> >      auto pidIn = File.tmpfile();
> >      auto pidOut = File.tmpfile();
> >      auto pid = spawnProcess(["ls", "./"], pidIn, pidOut,
> > std.stdio.stdout, null, Config.newEnv);
> >
> >      if(wait(pid) == 0)
> >          writefln("%s", pidOut.readln());
> > }
> >
> > The pidOut.readln() throws this exception:
> > object.Exception@/usr/include/dmd/phobos/std/stdio.d(1377):
> Attempt to
> > read from an unopened file.
> >
> > I figured tmpfile() would be open for read/write by default?
> > Also, theres no way to pass in args to File.tmpfile() to make
> them
> > read/write.
> >
> > Any ideas?
>
> It looks like the file is closed when spawnProcess is finished. I don't know whether it is done by spawnProcess explicitly or whether it is a behavior for temporary files.
>
> How about using a pipe? The following works:
>
> import std.stdio;
> import std.process;
>
> void main(string[] args)
> {
>     auto pidIn = File.tmpfile();
>     auto pidOut = pipe();
>     auto pid = spawnProcess(["ls", "./" ],
>                             pidIn, pidOut.writeEnd,
>                             std.stdio.stdout, null, Config.newEnv);
>
>     if(wait(pid) == 0)
>         writeln(pidOut.readEnd.byLine);
> }
>
> Ali

This works, Thanks folks!
February 26, 2015
On 2/25/15 2:09 PM, Ali Çehreli wrote:

> It looks like the file is closed when spawnProcess is finished. I don't
> know whether it is done by spawnProcess explicitly or whether it is a
> behavior for temporary files.

I know the problem is solved, but I wanted to chime in with some explanation here:

Yes, it's closed on purpose. Typically, when you open a file descriptor in order to have the child use it for stdin/stdout/stderr, you want to close the handle on the parent, since the parent isn't using it.

Even with pipes, there are 2 ends. The child uses one and closes the other, and the parent uses one and closes the other.

There is a way to disable this behavior, use Config.retainStdout.

http://dlang.org/library/std/process/config.html

The only time these aren't closed by default is if the default handles are used (you don't want to close e.g. stdout in the parent if you use it in the child).

-Steve