[Haskell-cafe] Fwd: Default stdout buffering of child process of createProcess

Elliot Robinson elliot.robinson at argiopetech.com
Sat Aug 2 06:49:27 UTC 2014


It's worth noting that `hGetNonBlocking` only works as described with GHC
on *nix. Windows and non-GHC treat it as a blocking hGet. Also, unless I'm
mistaken, my example leaks the Handle for the slave PTY (though it would be
trivial to fix).

---
Elliot Robinson
Phone: (321) 252-9660
Site: www.argiopetech.com
Email: elliot.robinson at argiopetech.com

PGP Fingerprint: 0xD1E72E6A9D0610FFBBF838A6FFB5205A9FEDE59A


On Sat, Aug 2, 2014 at 2:32 AM, Elliot Robinson <
elliot.robinson at argiopetech.com> wrote:

> I second pseudo-terminals. I find the System.Posix.Terminal to be very
> usable (though I've admittedly never tried System.Posix.Pty). I
> occasionally dabble with "bots" for terminal-based games (e.g., Nethack),
> and have used PTYs with some deal of success.
>
> I've included some code from a Nethack bot attempt from several years ago.
> Hopefully you'll find it useful. As a quick usage/rationale overview, I
> feed an attoparsec parser by repeatedly calling receive (intermixed with
> some intelligent use of `transmit` to deal with messages and other
> incomplete screen updates) until I receive a valid map. `hGetNonBlocking`
> bypasses the standard buffering mechanisms and returns whatever is in the
> PTY buffer (which may be nothing) rather than waiting for the specified
> line/block/whatever buffer to fill. `stop` and `start` should be obvious in
> their purpose, if not their implementation.
>
> data Local = Local { pty :: Handle }
>
> class Connection a where
>     transmit :: a -> ByteString -> IO ()
>     receive  :: a -> IO ByteString
>     stop     :: a -> IO ()
>     start    :: IO a
>
> instance Connection Local where
>     transmit l s = B.hPut (pty l) s
>     receive  l   = B.hGetNonBlocking (pty l) 4096
>     stop     l   = hClose $ pty l
>     start        = do
>         (fd1, fd2) <- openPseudoTerminal
>         (hPty) <- fdToHandle fd1
>         slave <- fdToHandle fd2
>         _<- createProcess (proc "sh" ["-c", "/usr/games/bin/nethack"]){
> std_in = (UseHandle slave), std_out = (UseHandle slave) }
>         return $ Local hPty
>
>
> Cheers,
> Elliot Robinson
> Phone: (321) 252-9660
> Site: www.argiopetech.com
> Email: elliot.robinson at argiopetech.com
>
>  PGP Fingerprint: 0xD1E72E6A9D0610FFBBF838A6FFB5205A9FEDE59A
>
>
> On Fri, Aug 1, 2014 at 11:20 PM, Brandon Allbery <allbery.b at gmail.com>
> wrote:
>
>> On Fri, Aug 1, 2014 at 11:07 PM, Chris Myzie <cmyzie28 at gmail.com> wrote:
>>
>>> As a workaround, I am able to trick the child haskell process into
>>> thinking it's running in an interactive terminal by wrapping it with
>>> /usr/bin/script:
>>>
>>
>> We discussed this on IRC the other day. Haskell is doing the same thing
>> that C/C++ stdio / iostreams, and most other buffering systems, do: line
>> buffering on terminal-like devices, block buffering on files and pipes.
>> This is generally expected behavior; although it can be confusing to new
>> programmers, ultimately it is more efficient for most programs.
>>
>> Interactive use like this, especially over pipes, is fairly unusual;
>> normally you're just copying data around /en masse/, and block buffering is
>> far more efficient. Note that line buffering is not and can not be
>> implemented at the kernel level for ordinary files or pipes, so the kernel
>> interface is actually character buffering which is extremely inefficient
>> (at least one context switch per individual character).
>>
>> You might want to search for something like "buffering line block pipes
>> files" to see quite a lot of discussion about it, in pretty much every
>> language you can think of.
>>
>> By the way, more efficient than using script(1) is, as I told you in IRC,
>> to use the mechanism it is using directly: pseudo-terminals (ptys). See
>> http://hackage.haskell.org/package/unix-2.7.0.1/docs/System-Posix-Terminal.html#g:6
>> for the standard pty stuff or
>> http://hackage.haskell.org/package/posix-pty-0.1.0/docs/System-Posix-Pty.html
>> for what is claimed to be a simpler interface intended for what you are
>> doing.
>>
>> --
>> brandon s allbery kf8nh                               sine nomine
>> associates
>> allbery.b at gmail.com
>> ballbery at sinenomine.net
>> unix, openafs, kerberos, infrastructure, xmonad
>> http://sinenomine.net
>>
>> _______________________________________________
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140802/617001e1/attachment-0001.html>


More information about the Haskell-Cafe mailing list