<div dir="ltr">Attaching a finalizer to a regular data type like that is a bit of a hazard prone process. If GHC unpack your Socket in another data constructor it will get "freed" and then your socket can get finalized while you still have access to the CInt! <div><br></div><div><div>data MySockets = MySockets {-# unpack #-} !Socket {-# unpack #-} !Socket</div><div><br></div><div>will happily 'eat' your data constructor wrapper and if there are no references remaining to a copy of it on the heap, their finalizers will fire. Worker-wrapper transforms can do this even without any "containing" data type if you just increase your optimization level!<div><br></div><div>It would be much, much safer to attach the finalizer to something that has a "presence" all its own, like <font face="monospace, monospace">Weak# ()</font> as is done in <font face="monospace, monospace">ForeignPtr. </font>This would result in something like:</div><div><br></div><div><font face="monospace, monospace">data Socket = Socket !CInt (Weak# ())</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">Then when it gets unpacked into another data constructor, then the </font><font face="monospace, monospace">Weak# ()</font><font face="arial, helvetica, sans-serif"> still exists. </font>This isn't free, it comes at the cost that your sockets take a couple of words each (plus finalizer space), but the approach you are taking now isn't free either as it isn't really sound. ;)</div><div><br></div><div><b>tl;dr</b> don't attach finalizers to regular Haskell data types if you can help it</div><div><br></div><div>-Edward</div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 30, 2018 at 12:18 AM, Kazu Yamamoto <span dir="ltr"><<a href="mailto:kazu@iij.ad.jp" target="_blank">kazu@iij.ad.jp</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
I registered this issue to network:<br>
<br>
        <a href="https://github.com/haskell/network/issues/302" rel="noreferrer" target="_blank">https://github.com/haskell/<wbr>network/issues/302</a><br>
<br>
Viktor, thank you!<br>
<span class="HOEnZb"><font color="#888888"><br>
--Kazu<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
>> On Jan 29, 2018, at 10:25 PM, Kazu Yamamoto (山本和彦) <<a href="mailto:kazu@iij.ad.jp">kazu@iij.ad.jp</a>> wrote:<br>
>><br>
>>    socket family stype protocol = do<br>
>>       fd <- c_socket ...<br>
>>       ...<br>
>>       let s = Socket fd<br>
>>       addFinalizer s $ close s<br>
>>       ruturn s<br>
><br>
> For the record, I think I've convinced Kazu Yamamoto that this is<br>
> an anti-pattern.  Such a finalizer would easily end up closing<br>
> already closed sockets, whose file-descriptors may already be<br>
> associated with other open files or sockets.  That way lie all<br>
> sorts of difficult to isolate race-condition bugs.  To make this<br>
> safe, the close function would need to mutate the socket,<br>
> invalidating the enclosed file-descriptor, and would then need to<br>
> be a NOP or just raise an exception if the socket is closed again<br>
> (the finalizer should invoke a close variant that just returns<br>
> without raising exceptions if the socket is already closed).<br>
><br>
> There is, AFAIK still an unresolved bug along these lines somewhere<br>
> in http-client and its dependencies.  So far no reproducing cases have<br>
> been provided.  No very recent reports either, perhaps it went away,<br>
> or people have just been more lucky lately:<br>
><br>
>    <a href="https://github.com/snoyberg/http-client/issues/252" rel="noreferrer" target="_blank">https://github.com/snoyberg/<wbr>http-client/issues/252</a><br>
>    <a href="https://github.com/vincenthz/hs-tls/issues/179" rel="noreferrer" target="_blank">https://github.com/vincenthz/<wbr>hs-tls/issues/179</a><br>
><br>
> All that said, the original question about addFinalizer vs. GHC 7.10<br>
> may still be worth exploring, even if its use-case for Sockets goes<br>
> away.  So, please don't take this poset to mean that the original<br>
> question should be ignored.<br>
><br>
> --<br>
>       Viktor.<br>
><br>
> ______________________________<wbr>_________________<br>
> Haskell-Cafe mailing list<br>
> To (un)subscribe, modify options or view archives go to:<br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
> Only members subscribed via the mailman list are allowed to post.<br>
______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</div></div></blockquote></div><br></div>