[Haskell-cafe] Fwd: Default stdout buffering of child process of createProcess
Elliot Robinson
elliot.robinson at argiopetech.com
Sat Aug 2 06:32:46 UTC 2014
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/275fe31b/attachment.html>
More information about the Haskell-Cafe
mailing list