
On Sat, May 4, 2013 at 8:50 AM, Edward Z. Yang
Akio, your derefWeak WHITEHOLE fix looks really weird. I don't know what the right pattern is, but it seems like asking for trouble when there are multiple concurrent derefs:
if (info == stg_WHITEHOLE_info) { ("ptr" info) = ccall lockClosure(w "ptr"); unlockClosure(w, info); }
I don't see what the problem is, could you elaborate? The purpose of the fix was to prevent a sequence like this: - w is a dead weak pointer. - Thread A: finalizeWeak# w. - Thread A: finalizeWeak# calls lockClosure(w), overwriting w->info with stg_WHITEHOLE_info. - Thread B: deRefWeak# w - Thread B: deRefWeak# sees stg_WHITEHOLE_info, and since it's not the same as stg_DEAD_WEAK_info, it thinks w is alive. The problem was that if deRefWeak# saw stg_WHITEHOLE_info, it was not clear whether the weak pointer was alive or not. So my fix adds a call to lockClosure, which never returns stg_WHITEHOLE_info.
addForeignPtrFinalizer retries in this case.
This can't be right; a dead weak pointer always stays dead, so won't this infinite loop?
No. When addForeignPtrFinalizer retries, it will use a new Weak# object, because foreignPtrFinalizer must have been replaced the content of the IORef.
I haven't got around to looking at this, but I see Edward is on the case with some code review. Do you think I should look at it before it goes in?
Now you're asking for it :) I would always be interested in seeing if I missed anything.
Cheers, Edward