You should use an MVar if you want it to be thread safe.<br><br><div class="gmail_quote">On Jan 19, 2008 1:36 PM, David Roundy &lt;<a href="mailto:droundy@darcs.net">droundy@darcs.net</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Using ghc 6.6, but I&#39;ve since isolated the bug as being unrelated to the<br>IORefs and threading, it was in an FFI binding that somehow never died<br>until I was testing this new code.<br><font color="#888888"><br>David<br>
</font><div><div></div><div class="Wj3C7c"><br>On Sat, Jan 19, 2008 at 01:27:47PM +0100, Peter Verswyvelen wrote:<br>&gt; Hi David,<br>&gt;<br>&gt; Which version of GHC are you using?<br>&gt;<br>&gt; I tried to recompile some GHC 6.6.1 progs using GHC 6.8.2 and I also got<br>
&gt; segfaults. I haven&#39;t figured out yet if this is because my changes to<br>&gt; make it work with GHC 6.8.2 are incorrect, or if this is an issue with<br>&gt; 6.8.2.<br>&gt;<br>&gt; Cheers,<br>&gt; Peter<br>&gt;<br>
&gt;<br>&gt; On Fri, 2008-01-18 at 18:22 -0500, David Roundy wrote:<br>&gt; &gt; Hi all,<br>&gt; &gt;<br>&gt; &gt; I&#39;m working on some new progress-reporting code for darcs, and am getting<br>&gt; &gt; segmentation faults! &nbsp;:( The code uses threads + an IORef global variable<br>
&gt; &gt; to do this (with lots of unsafePerformIO). &nbsp;So my question for the gurus<br>&gt; &gt; who know more about this than I do: &nbsp;is this safe? I thought it would be,<br>&gt; &gt; because only one thread ever modifies the IORef, and the others only read<br>
&gt; &gt; it. &nbsp;I don&#39;t really care if they read a correct value, as long as they<br>&gt; &gt; don&#39;t segfault.<br>&gt; &gt;<br>&gt; &gt; The code (to summarize) looks like:<br>&gt; &gt;<br>&gt; &gt; {-# NOINLINE _progressData #-}<br>
&gt; &gt; _progressData :: IORef (Map String ProgressData)<br>&gt; &gt; _progressData = unsafePerformIO $ newIORef empty<br>&gt; &gt;<br>&gt; &gt; updateProgressData :: String -&gt; (ProgressData -&gt; ProgressData) -&gt; IO ()<br>
&gt; &gt; updateProgressData k f = when (progressMode) $ modifyIORef _progressData (adjust f k)<br>&gt; &gt;<br>&gt; &gt; setProgressData :: String -&gt; ProgressData -&gt; IO ()<br>&gt; &gt; setProgressData k p = when (progressMode) $ modifyIORef _progressData (insert k p)<br>
&gt; &gt;<br>&gt; &gt; getProgressData :: String -&gt; IO (Maybe ProgressData)<br>&gt; &gt; getProgressData k = if progressMode then lookup k `fmap` readIORef _progressData<br>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else return Nothing<br>
&gt; &gt;<br>&gt; &gt; The key function is<br>&gt; &gt;<br>&gt; &gt; beginTedious :: String -&gt; IO ()<br>&gt; &gt; beginTedious k = do tid &lt;- forkIO $ handleProgress k<br>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; debugMessage $ &quot;Beginning &quot; ++ k<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setProgressData k $ ProgressData { sofar = 0,<br>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;latest = Nothing,<br>&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;total = Nothing,<br>
&gt; &gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;handler = Just tid }<br>&gt; &gt;<br>&gt; &gt; which is called before an action that may be so tedious for our users that<br>&gt; &gt; they need their day brightened by messages such as &quot;Applying patch<br>
&gt; &gt; 137/1436&quot;. &nbsp;The handleProgress function alternates between threadDelay and<br>&gt; &gt; reading the progress data to see whether any progress has been made and<br>&gt; &gt; printing messages. &nbsp;Meanwhile the main thread calls functions that update<br>
&gt; &gt; _progressData.<br>&gt; &gt;<br>&gt; &gt; Anyhow, the point is that I&#39;m getting segfaults, even after recompiling<br>&gt; &gt; everything from scratch! Is this in fact that unsafe? Do I really need to<br>&gt; &gt; switch to MVars, even though no locking is required?<br>
&gt;<br>&gt; _______________________________________________<br>&gt; Haskell-Cafe mailing list<br>&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br></div></div><div class="Ih2E3d">--<br>David Roundy<br>Department of Physics<br>Oregon State University<br>_______________________________________________<br></div><div><div></div><div class="Wj3C7c">Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br></div></div>
</blockquote></div><br>