Re: [Haskell-cafe] Preventing leaked open file descriptors whencatching exceptions

2012-02-22 Thread Albert Y. C. Lai
I cannot reproduce pretty much any claim made in this thread. Unless PIO 
does not mean System.IO.Posix.


I run mkfifo hello to create a named pipe. Then I run this program to 
keep trying to open for writing, non-blocking (without anyone at the 
read end initially):


import System.Posix.IO
import System.Posix.Types(Fd(..))
import qualified Control.Exception as E
import Control.Concurrent(threadDelay)

main = do
  E.handle
(\e - putStrLn (caught exception:  ++ show (e :: E.IOException)))
-- you can change IOException to SomeException too
(do fd - openFd hello WriteOnly Nothing
defaultFileFlags{nonBlock=True}
case fd of Fd n - putStrLn (fd number  ++ show n)
-- I deliberately leak fd
)
  threadDelay 150
  main

openFd failures are successfully caught as exceptions; it does not 
return an Fd that stands for -1 when it fails. (Check its source code 
and chase down what throwErrnoPathIfMinus1Retry means.)


When it fails, it does not leak file descriptors. lsof hello shows 
nothing.


To force file descriptors to be leaked and see what lsof says, I then 
run cat hello as the read end while the above program is still 
running, so that openFd succeeds and I have something to leak. lsof 
hello successfully shows:


COMMAND  PID   USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
f   3725 trebla3w  FIFO8,5  0t0 158922 hello
f   3725 trebla4w  FIFO8,5  0t0 158922 hello
f   3725 trebla5w  FIFO8,5  0t0 158922 hello
f   3725 trebla6w  FIFO8,5  0t0 158922 hello
cat 3726 trebla3r  FIFO8,5  0t0 158922 hello

My point is that if openFd ... WriteOnly leaks anything, you should be 
seeing 3w, 4w, etc., emphasis on w. But you're seeing a ton of rs. 
Your leaker is some read-end code.


Ubuntu 11.04 x86 32-bit, kernel 2.6.38, GHC 6.12.3, 7.0.4, 7.2.1, 7.4.1

Lastly, the control structure

loop = handle (\e - ... loop) job

is very problematic. Go to the haddock of Control.Exception, search for 
the string The difference between using try and catch for recovery to 
see why. You should use this:


loop = do
  lr - try job
  case lr of
Left e - ... loop
Right a - return a

i.e., get out of the exception handler as soon as possible. (Thus, my 
use of putStrLn inside a handler is also questionable. But mine is a 
toy. I wouldn't do it in production code.)


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Preventing leaked open file descriptors whencatching exceptions

2012-02-21 Thread Donn Cave
Quoth Bryan O'Sullivan b...@serpentine.com,
 On Tue, Feb 21, 2012 at 8:16 AM, Ryan Newton rrnew...@gmail.com wrote:

 FYI, lsof confirms that there are indeed many many open connections to the
 same FIFO:


 Like all of the lowest-level I/O functions, openFD just gives you back an
 integer, and the Fd type has no notion that there's an underlying system
 resource associated with it. It's your responsibility to manage it (i.e.
 clean up manually when catching an exception).

What's more - if I understood the hypothesis correctly, that the
exception occurs during openFd - that fails to return an Fd because
the open(2) system call fails to return one, so it would presumably
be an OS level bug if there's really an open file descriptor left
from this.

Donn

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Preventing leaked open file descriptors whencatching exceptions

2012-02-21 Thread Ryan Newton
Ah, thanks Bryan.  I hadn't looked into it enough to realize that FDs are
just ints and not ForeignPtrs w/ finalizers.

Re: Donn's point.  Well, yes, that would seem to be the case!  But since I
think a linux bug is unlikely, I'm afraid that there's something else going
on here which I am not thinking of.

I'll make a self contained test of this and send it out.


On Tue, Feb 21, 2012 at 12:53 PM, Donn Cave d...@avvanta.com wrote:

 Quoth Bryan O'Sullivan b...@serpentine.com,
  On Tue, Feb 21, 2012 at 8:16 AM, Ryan Newton rrnew...@gmail.com wrote:
 
  FYI, lsof confirms that there are indeed many many open connections to
 the
  same FIFO:
 
 
  Like all of the lowest-level I/O functions, openFD just gives you back an
  integer, and the Fd type has no notion that there's an underlying system
  resource associated with it. It's your responsibility to manage it (i.e.
  clean up manually when catching an exception).

 What's more - if I understood the hypothesis correctly, that the
 exception occurs during openFd - that fails to return an Fd because
 the open(2) system call fails to return one, so it would presumably
 be an OS level bug if there's really an open file descriptor left
 from this.

Donn

 ___
 Haskell-Cafe mailing list
 Haskell-Cafe@haskell.org
 http://www.haskell.org/mailman/listinfo/haskell-cafe

___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe