[Haskell-cafe] Windows: openFile gives permission denied when file in use
michael at snoyman.com
Thu Dec 29 09:43:35 CET 2011
On Thu, Dec 29, 2011 at 3:45 AM, Antoine Latter <aslatter at gmail.com> wrote:
> On Wed, Dec 28, 2011 at 3:52 PM, Michael Snoyman <michael at snoyman.com> 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:
> 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:
> 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.
Thanks for the advice Antoine, it was spot on. I modified my
uri-conduit package with the following commit:
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
Does anyone see any issues with the code? Would it be useful for me to
expose this code elsewhere, such as in conduit itself?
More information about the Haskell-Cafe