withSystemTempFileで取得した一時ファイルに書き込む外部プロセスを呼び出そうとしています。プロセスが終了した後、cat
そのファイルの内容を確認することはできopenFile: resource busy (file is locked)
ますが、readFileを使用してそのファイルを読み取ろうとすると、アプリケーション自体がエラーで失敗します。私はこの質問への回答の提案に従い、怠惰なバージョンのを使用しましたreadFile
。コード例は次のとおりです。
module Main where
import Prelude hiding (readFile)
import System.Process (createProcess, shell)
import System.IO (Handle, hShow)
import System.IO.Temp (withSystemTempFile)
import System.IO.Strict (readFile)
main :: IO ()
main = withSystemTempFile "temp.txt" doSomeStuff
where
doSomeStuff :: FilePath -> Handle -> IO ()
doSomeStuff tempFilePath tempFilePathHandle = do
putStrLn tempFilePath
createProcess $ shell $ "echo \"test\" >> " ++ tempFilePath
getLine -- It's here just to stop program while I check that I can actually "cat" the temp file
-- here I'm able to cat the temp file
contents <- readFile tempFilePath -- here the command fails with /tmp/temp23900-0.txt: openFile: resource busy (file is locked)
putStrLn contents
私はまだHaskellに頭を悩ませているので、アイデアが足りなくなったので、それが明白なことではないことを願っています。何が得られますか?
このエラーはwithSystemTempFile
、入力時にファイルがロックされるためです。代わりに(tempFilePathHandle
コードで呼び出される)ハンドルを提供するため、次のようにハンドルを使用してファイルを読み取ることができます。
contents <- hGetContents tempFilePathHandle
編集
これは、GHCが内部でリーダーライターロックを実装して、開いたファイルと必要なアクセス許可を追跡するためです。リーダーライターロックは、1人のライター(排他的アクセス)または複数のリーダー(共有アクセス)のいずれかを許可します。
この場合、withSystemTempFile
一時ファイルでライターロックをreadFile
取得するため、必要なリーダーロックを取得できません(この場合も、ライターロックにより、GHCがそのファイルでリーダーロックを取得できなくなります)。
これは、ロックを実装するCコードへのリンクです。@luquiが以下のコメントで示唆しているように、特にGHCがOSレベルのロックを要求しないため、これはおそらく最適なソリューションではないため、のようなプロセスcat
は引き続きファイルにアクセスして変更できます。ファイルの読み取りと書き込みが予測しにくい結果を生成する怠惰なコンテキストでは、より意味があるかもしれません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加