
On Thu, Dec 29, 2011 at 3:45 AM, Antoine Latter
On Wed, Dec 28, 2011 at 3:52 PM, Michael Snoyman
wrote: Hi all,
I just received a bug report from a client that, when an input file is open in FrameMaker, my program gives a "permission denied error". This bug is reproducible with a simple Haskell program:
import System.IO
main = do putStrLn "here1" h <- openFile "filename.txt" ReadMode putStrLn "here2"
I tried writing a simple C program using fopen, and it ran just fine. Does anyone have experience with this issue, and know of a workaround?
When GHC opens files for reading, it asks windows to disallow write access to the file. I'm guessing that Framemaker has the file open for writing, so GHC can't get that permission.
I imagine that the Haskell runtime does this to make lazy-io less crazy.
Here's the call GHC makes: https://github.com/ghc/packages-base/blob/0e1a02b96cfd03b8488e3ff4ce232466d6...
To open a file for reading in your C demo in a similar way you could do something like:
fd = _sopen("file_name", _O_RDONLY | _O_NOINHERIT,_SH_DENYWR, 0);
Here "_SH_DENYWR" is telling windows to deny others from writing to this file.
Here's the msdn link for _sopen and _wsopen: http://msdn.microsoft.com/en-us/library/w7sa2b22%28VS.80%29.aspx
I haven't tested any of that, but that should help you in reproducing how GHC opens files for read on windows.
You should be able to use System.Win32.File.createFile with a share mode of (fILE_SHARE_READ .|. fILE_SHARE_WRITE) and then wrangling a Haskell Handle out of that, but I haven't tried it.
Or you could modify the call to _wsopen and FFI call that - it takes fewer parameters and might be less confusing.
Antoine
Thanks for the advice Antoine, it was spot on. I modified my uri-conduit package with the following commit: https://github.com/snoyberg/xml/commit/a4763739093c525d8f509b11e72a2d17894af... Since conduits re-implement buffering themselves, I don't think there's any advantage to wrapping up the FD in a Handle again, except perhaps for better integration with the async calls of the multi-threaded runtime. But since I'm not using that for my Windows code, and I don't think the multi-threaded runtime supports Windows particularly well in the first place, this seems like an acceptable trade-off. Does anyone see any issues with the code? Would it be useful for me to expose this code elsewhere, such as in conduit itself? Michael