Package: libghc-missingh-dev
Version: 1.1.0.3-6+b3
Severity: normal

As described in this thread:
http://thread.gmane.org/gmane.comp.lang.haskell.cafe/99334/focus=99338

The attached testcase will hang after a short while once compiled with 
-threaded.
Comment out the "LINE OF DEATH" and it runs as expected.

Apparently hPipeFrom etc's use of System.Log.Logger is the culprit. logM uses
a MVar, and this is a MVar deadlock. But I don't understand exactly why this
happens only with the threaded runtime, or really, why the attempt to use the 
MVar
*before* forkProcess causes problems at all.

This also seems disturbingly similar to #624389. In both cases System.Cmd.Utils
falls over under heavy load, or is somehow racy.

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: i386 (x86_64)

Kernel: Linux 3.2.0-2-amd64 (SMP w/1 CPU core)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages libghc-missingh-dev depends on:
ii  ghc [libghc-unix-dev-2.5.1.0-b1af7]                        7.4.1-4
ii  libc6                                                      2.13-32
ii  libffi5                                                    3.0.10-3
ii  libghc-array-dev-0.4.0.0-0b32f                             <none>
ii  libghc-base-dev-4.5.0.0-c8e71                              <none>
ii  libghc-containers-dev-0.4.2.1-7c545                        <none>
ii  libghc-directory-dev-1.1.0.2-89575                         <none>
ii  libghc-filepath-dev-1.3.0.0-674b8                          <none>
ii  libghc-hslogger-dev [libghc-hslogger-dev-1.1.4-94350]      1.1.4+dfsg1-2+b3
ii  libghc-hunit-dev [libghc-hunit-dev-1.2.4.2-6a847]          1.2.4.2-2+b1
ii  libghc-mtl-dev [libghc-mtl-dev-2.1.1-ae9b4]                2.1.1-1
ii  libghc-network-dev [libghc-network-dev-2.3.0.13-6b330]     2.3.0.13-1+b2
ii  libghc-old-locale-dev-1.0.0.4-29bd5                        <none>
ii  libghc-old-time-dev-1.1.0.0-681e9                          <none>
ii  libghc-parsec3-dev [libghc-parsec-dev-3.1.2-ad4f8]         3.1.2-1+b3
ii  libghc-process-dev-1.1.0.1-91185                           <none>
ii  libghc-random-dev [libghc-random-dev-1.0.1.1-3bece]        1.0.1.1-1+b1
ii  libghc-regex-compat-dev [libghc-regex-compat-dev-0.95.1-c  0.95.1-2+b1
ii  libgmp10                                                   2:5.0.5+dfsg-2

libghc-missingh-dev recommends no packages.

Versions of packages libghc-missingh-dev suggests:
pn  libghc-missingh-doc   <none>
pn  libghc-missingh-prof  <none>

-- no debconf information

-- 
see shy jo
import System.Cmd
import System.IO
import System.Posix.Process
import Control.Monad
import System.Exit
import System.Cmd
import System.Log.Logger
import System.Posix.IO
import System.Posix.Process
import System.Posix.Signals
import System.Posix.Types
import System.IO
import System.IO.Error
import Control.Concurrent(forkIO)
import Control.Exception(finally)

main :: IO ()
main = forever $ 
	pipeRead ["hello", "world"]

pipeRead :: [String] -> IO ()
pipeRead params = do
	print $ "pipeRead in " ++ show (params)
	(p, h) <- hPipeFrom "echo" params
	print "pipeRead getcontents"
	c <- hGetContents h
	print $ "got: " ++ c
	_ <- getProcessStatus True False $ processID p
	print "pipeRead out"

data PipeHandle =
    PipeHandle { processID :: ProcessID,
                 phCommand :: FilePath,
                 phArgs :: [String],
                 phCreator :: String -- ^ Function that created it
               }
    deriving (Eq, Show)

logRunning :: String -> FilePath -> [String] -> IO ()
logRunning func fp args = debugM (logbase ++ "." ++ func) (showCmd fp args)

logbase :: String
logbase = "System.Cmd.Utils"

showCmd :: FilePath -> [String] -> String
showCmd fp args = fp ++ " " ++ show args

warnFail :: [Char] -> FilePath -> [String] -> [Char] -> IO t
warnFail funcname fp args msg =
    let m = showCmd fp args ++ ": " ++ msg
        in do warningM (logbase ++ "." ++ funcname) m
              fail m

hPipeFrom :: FilePath -> [String] -> IO (PipeHandle, Handle)
hPipeFrom fp args =
    do pipepair <- createPipe
       logRunning "pipeFrom" fp args --- LINE OF DEATH
       let childstuff = do dupTo (snd pipepair) stdOutput
                           closeFd (fst pipepair)
                           executeFile fp True args Nothing
       p <- try (forkProcess childstuff)
       -- parent
       pid <- case p of
                  Right x -> return x
                  Left e -> warnFail "pipeFrom" fp args $
                            "Error in fork: " ++ show e
       closeFd (snd pipepair)
       h <- fdToHandle (fst pipepair)
       return (PipeHandle pid fp args "pipeFrom", h)

Reply via email to