Debugging Haskell
Jerry, JiJie
jerry@gime.com
Sat, 9 Mar 2002 23:01:21 +0800
--wRRV7LY7NUeQGEoC
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Good day everyone, I was fiddling around with this tiny echo
client/server haskell program from 'The Great Language Shootout'
site (http://www.bagley.org/~doug/shootout/) and got stuck.
The code (attached) has been reformatted with minimal API tweak
(mkPortNumber, writeSocket, readSocket) to please my ghc-5.02.2, and
all what I get is something stuck forever after the first
iteration:
$ ./echo 3
Client wrote: Hello there sailor
Server recv: Hello there sailor
Server read: Hello there sailor
Server wrote: Hello there sailor
After adding all these print statement, I still don't have a clue
what's jammed there. Hope someone here can shred some light.
BTW, I'd also like to take this chance to ask how to debug a haskell
program in general?
Regards,
Jerry
--wRRV7LY7NUeQGEoC
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="echo.hs"
-- $Id: echo.ghc,v 1.2 2001/05/01 20:19:52 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- Haskell echo/client server
-- written by Brian Gregor
-- compile with:
-- ghc -O -o echo -package net -package concurrent -package lang echo.hs
module Main where
import SocketPrim
import Concurrent
import System (getArgs,exitFailure)
import Exception(finally)
import MVar
server_sock :: IO (Socket)
server_sock = do
s <- socket AF_INET Stream 6
setSocketOption s ReuseAddr 1
-- bindSocket s (SockAddrInet (mkPortNumber portnum) iNADDR_ANY)
bindSocket s (SockAddrInet (PortNum portnum) iNADDR_ANY)
listen s 2
return s
echo_server s = do
(s', clientAddr) <- accept s
proc <- read_data s' 0
putStrLn ("server processed "++(show proc)++" bytes")
sClose s'
where
read_data sock totalbytes = do
-- (str,i) <- readSocket sock 19
str <- recv sock 19
-- if (i >= 19)
putStr ("Server recv: " ++ str)
if ((length str) >= 19)
then do
putStr ("Server read: " ++ str)
-- writ <- writeSocket sock str
writ <- send sock str
putStr ("Server wrote: " ++ str)
--
read_data sock $! (totalbytes+(length $! str))
-- read_data sock (totalbytes+(length str))
else do
putStr ("server read: " ++ str)
return totalbytes
local = "127.0.0.1"
message = "Hello there sailor\n"
portnum = 7001
client_sock = do
s <- socket AF_INET Stream 6
ia <- inet_addr local
-- connect s (SockAddrInet (mkPortNumber portnum) ia)
connect s (SockAddrInet (PortNum portnum) ia)
return s
echo_client n = do
s <- client_sock
drop <- server_echo s n
sClose s
where
server_echo sock n = if n > 0
then do
-- writeSocket sock message
send sock message
putStr ("Client wrote: " ++ message)
--
-- (str,i) <- readSocket sock 19
str <- recv sock 19
if (str /= message)
then do
putStr ("Client read error: " ++ str ++ "\n")
exitFailure
else do
putStr ("Client read success")
server_echo sock (n-1)
else do
putStr "Client read nil\n"
return []
main = do
~[n] <- getArgs
-- server & client semaphores
-- get the server socket
ssock <- server_sock
-- fork off the server
s <- myForkIO (echo_server ssock)
-- fork off the client
c <- myForkIO (echo_client (read n::Int))
-- let 'em run until they've signaled they're done
join s
putStr("join s")
join c
putStr("join c")
-- these are used to make the main thread wait until
-- the child threads have exited
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
forkIO (io `finally` putMVar mvar ())
return mvar
join :: MVar () -> IO ()
join mvar = readMVar mvar
--wRRV7LY7NUeQGEoC--