<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Sorry, I should have addressed this to Johan rather than Otto!<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jul 22, 2022, at 2:13 PM, James Foster via GemStone-Smalltalk <<a href="mailto:gemstone-smalltalk@lists.gemtalksystems.com" class="">gemstone-smalltalk@lists.gemtalksystems.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Otto,<div class=""><br class=""></div><div class="">I believe that GemStone’s support for weak references is limited to in-memory objects, not persistent objects. While there is some discussion of adding ephemerons to persistent objects, it isn’t there now.<div class=""><br class=""></div><div class="">Recently Martin entered our internal issue number 50024 ("Oop-fishing between vote and reclaim can result in holding a dead object”), describing it as “theoretical, not yet reproduced.” You might have demonstrated that problem (or something related).</div><div class=""><br class=""></div><div class="">In any case, I think that the safer thing for you to do is to assign your own unique identifiers to your objects and use that unique identifier in your logging. With that, you wouldn’t need to add an object creation date and do oop-fishing. </div><div class=""><br class=""></div><div class="">James<br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jul 22, 2022, at 12:37 PM, Wai Lun Mang via GemStone-Smalltalk <<a href="mailto:gemstone-smalltalk@lists.gemtalksystems.com" class="">gemstone-smalltalk@lists.gemtalksystems.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><!--[if gte mso 9]><xml><o:OfficeDocumentSettings><o:AllowPNG/><o:PixelsPerInch>96</o:PixelsPerInch></o:OfficeDocumentSettings></xml><![endif]--><div class="">
GemStone does have weak references support. One of my previous project called Iris2 had been using it for a long time.<div class=""><br class=""></div><div class="">You can asked Norm Green about the weak reference support.</div><div class=""><br class=""></div><div class="">Mang<br class=""><br class=""><br class=""><a href="https://overview.mail.yahoo.com/?.src=iOS" class="">Sent from Yahoo Mail for iPhone</a><br class=""><br class=""><p class="yahoo-quoted-begin" style="font-size: 15px; color: #715FFA; padding-top: 15px; margin-top: 0">On Friday, July 22, 2022, 9:44 AM, Otto Behrens via GemStone-Smalltalk <<a href="mailto:gemstone-smalltalk@lists.gemtalksystems.com" class="">gemstone-smalltalk@lists.gemtalksystems.com</a>> wrote:</p><blockquote class="iosymail"><div id="yiv6830374383" class=""><div class=""><div dir="ltr" class=""><div class="yiv6830374383gmail_quote"><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex;" class="yiv6830374383gmail_quote"><div class=""><div class=""><div class="">We only see this happening after an MFC and only occasionally and also only from within gems that have been running before the MFC. <br clear="none" class=""></div></div></div></blockquote><div class=""><br clear="none" class=""></div><div class="">Ok. We never run a full MFC with seaside sessions up. MFC works better if you can stop as many processes as possible. This is because it does a complete sweep of the repository. We rely on the Epoch GC to mark objects as possibly dead. There may be a subtle difference. The reclaim gem will come later and claim the space. This is my layman's understanding. I see you use oopIsDead when the space it occupies has not been reclaimed yet. I remember there may be some more complexity around the "deadness" of an object.</div><div class=""> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex;" class="yiv6830374383gmail_quote"><div class=""><div class=""><div class=""></div><div class="">Since the oop lookup is part of rendering the log entries in our Seaside application, connected users can trigger this error. The stack trace I pasted was triggered multiple times from the same gem, while Seaside requests handled by other gems were processing the same data (i.e. log entries) without errors at the same time (probably getting a nil result for the objectForOop:, as expected).</div><div class=""><br clear="none" class=""></div></div><div class="">So, the error probably occurs at the first access to the instance variable of the object we retrieved via _objectForOop:. Since the place in the stack trace where the error is thrown is indeed the first time we access the instVar with the object that is reported missing, that is probably what is happening. Indeed.</div></div></blockquote><div class=""><br clear="none" class=""></div><div class="">I don't understand what you mean by "the instance variable of the object we retrieved via _objectForOop:". Are you saying that the object returned by _objectForOop: (which is now marked dead by the MFC) refers to another object, which may now also be possibly dead? Is it perhaps possible that your access modifies the object? I don't see the correlation: why accessing the instVar should have anything to do with it, unless there is a side effect on the accessing.</div><div class=""> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex;" class="yiv6830374383gmail_quote"><div class=""><div class="">Unfortunately, I would expect _oopIsDead: to report the object as being dead in that case and thus not return us the object. </div></div></blockquote><div class=""><br clear="none" class=""></div><div class="">I agree, unless it is somehow re-attached. I think this is possible. Getting hold of an object that was marked as dead can somehow resurrect it, even if the gem that accessed it has the reference in transient memory. Perhaps this has something to do with it: there is a reference now (after looking at it) or the dead object was moved to a location meant for objects that are not dead.</div><div class=""><br clear="none" class=""></div><div class="">The block passed to ifNil:ifNotNil: in your code below could be a complex block, which means that there could be a copy of the invocation in memory that would now refer to "object".</div><div class=""><br clear="none" class=""></div><div class="">I'm not sure if #ifNil:ifNotNil: is optimised by the compiler in the version you are using. I know that there are some more optimisations in 3.6. There is an issue with calling </div><div class=""><br clear="none" class=""></div><div class=""><div class=""> (SystemRepository _oopIsDead: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifTrue: aBlock</div></div><div class="">because I think it cannot be optimised by the compiler (aBlock is sent to #ifTrue:ifFalse:), but if you do </div><div class=""><div class=""> (SystemRepository _oopIsDead: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifTrue: [ aBlock value ]</div></div><div class="">the ifTrue:ifFalse: call is optimised.</div><div class=""><br clear="none" class=""></div><div class="">This probably has nothing to do with your issue.</div><div class=""><br clear="none" class=""></div><div class="">Perhaps consider something like this. I know the multiple exit points are not as nice. But there is some logic to what the compiler can do.</div><div class=""><br clear="none" class=""></div><div class=""><div class="">privateObjectAtUniqueIdentifier: anInteger ifAbsent: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> | object |</span></div><div class=""><span style="white-space:pre-wrap;" class=""> </span>(object := Object _objectForOop: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifNil: [ ^ aBlock value ].</div></div><div class=""><span style="white-space:pre-wrap;" class=""> ^ </span>(SystemRepository _oopIsDead: anInteger)<br clear="none" class=""></div><div class=""><span style="white-space:pre-wrap;" class=""> ifTrue: [ aBlock value ]</span><br clear="none" class=""></div><div class=""><span style="white-space:pre-wrap;" class=""> ifFalse: [ object ]</span></div><div class=""><span style="white-space:pre-wrap;" class=""><br clear="none" class=""></span></div><div class=""><span style="white-space:pre-wrap;" class="">I wonder what will happen if you call _oopIsDead: first. Perhaps this will guard it from failing.</span></div><div class=""><span style="white-space:pre-wrap;" class=""><br clear="none" class=""></span></div><div class=""><span style="white-space:pre-wrap;" class="">Just an old hacker trying things.</span></div><div id="yiv6830374383yqtfd87777" class="yiv6830374383yqt7378464838"><div class=""><span style="white-space:pre-wrap;" class=""><br clear="none" class=""></span></div><div class=""><span style="white-space:pre-wrap;" class="">:-)</span></div><div class=""> </div><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex;" class="yiv6830374383gmail_quote"><div class=""><div class="">The implementation where we invoke _objectForOop: is shown below. First the version of the method as it was when the error occurred then the new version where I tried to the ‘fix’ it by wrapping the error handler around the entire code.</div><div class=""><div class=""><br clear="none" class=""></div><div class=""><div class="">privateObjectAtUniqueIdentifier: anInteger ifAbsent: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>^ (Object _objectForOop: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifNil: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifNotNil:[ :object | [ (SystemRepository _oopIsDead: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifTrue: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifFalse: [ object ] ] on: Error do: [:e | aBlock value ] ]</div><div class=""><br clear="none" class=""></div><div class=""><br clear="none" class=""></div><div class=""><div class="">privateObjectAtUniqueIdentifier: anInteger ifAbsent: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>^ [ (Object _objectForOop: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifNil: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifNotNil:[ :object | (SystemRepository _oopIsDead: anInteger)</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifTrue: aBlock</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>ifFalse: [ object ] ] </div><div class=""><span style="white-space:pre-wrap;" class=""> </span>] on: Error do: [:e | </div><div class=""><span style="white-space:pre-wrap;" class=""> </span>"oop fishing in GemStone may return internal objects that do not implement ifNil:ifNotNil:.</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>_oopIsDead can also error (see method comment). </div><div class=""><span style="white-space:pre-wrap;" class=""> </span>capture these objects here and return nil"</div><div class=""><span style="white-space:pre-wrap;" class=""> </span>aBlock value ]</div></div></div></div></div>_______________________________________________<br clear="none" class="">
GemStone-Smalltalk mailing list<br clear="none" class="">
<a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" target="_blank" href="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" class="">GemStone-Smalltalk@lists.gemtalksystems.com</a><br clear="none" class="">
<a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk" class="">https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk</a><br clear="none" class="">
</blockquote></div></div></div><div id="yiv6830374383yqtfd77604" class="yiv6830374383yqt7378464838">
</div></div></div><div class="yqt7378464838" id="yqtfd03311">_______________________________________________<br clear="none" class="">GemStone-Smalltalk mailing list<br clear="none" class=""><a shape="rect" ymailto="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" href="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" class="">GemStone-Smalltalk@lists.gemtalksystems.com</a><br clear="none" class=""><a shape="rect" href="https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk" target="_blank" class="">https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk</a><br clear="none" class=""></div><blockquote class=""></blockquote></blockquote></div>
</div>_______________________________________________<br class="">GemStone-Smalltalk mailing list<br class=""><a href="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" class="">GemStone-Smalltalk@lists.gemtalksystems.com</a><br class=""><a href="https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk" class="">https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk</a><br class=""></div></blockquote></div><br class=""></div></div></div></div>_______________________________________________<br class="">GemStone-Smalltalk mailing list<br class=""><a href="mailto:GemStone-Smalltalk@lists.gemtalksystems.com" class="">GemStone-Smalltalk@lists.gemtalksystems.com</a><br class="">https://lists.gemtalksystems.com/mailman/listinfo/gemstone-smalltalk<br class=""></div></blockquote></div><br class=""></body></html>