[GemStone-Smalltalk] objectForOop: question about some errors we get + how to implement a weak reference?

Johan Brichau johan at yesplan.be
Fri Jul 22 08:10:56 PDT 2022


Hi Otto,

> When an object does not exist, the method has always returned nil. I've never seen an exception thrown when calling _objectForOop:

We only see this happening after an MFC and only occasionally and also only from within gems that have been running before the MFC. 
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).

> The stack trace entry for 
> privateObjectAtUniqueIdentifier:in:ifAbsent:
> does not tell me what is happening. Perhaps this is optimised by the compiler? How do you know that this is calling _objectForOop: and that it is _objectForOop: that raises the InternalError?

It _is_ calling _objectForOop: but you are right: the stack trace does indeed not show this. In fact, there are several method calls in between privateObjectAtUniqueIdentifier:in:ifAbsent: and _objectForOop: …. The _objectForOop: send occurs in another method with a similar name `privateObjectAtUniqueIdentifier:ifAbsent:`  which is implemented on another class, but it _is_ being called from NPLogEntry>>privateObjectAtUniqueIdentifier:in:ifAbsent: 
Thanks for point that out… the similarity in names made me miss that.

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.

Unfortunately, I would expect _oopIsDead: to report the object as being dead in that case and thus not return us the object. 
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.

privateObjectAtUniqueIdentifier: anInteger ifAbsent: aBlock
	^ (Object _objectForOop: anInteger)
		ifNil: aBlock
		ifNotNil:[ :object | [ (SystemRepository _oopIsDead: anInteger)
							ifTrue: aBlock
							ifFalse: [ object ] ] on: Error do: [:e | aBlock value ] ]


privateObjectAtUniqueIdentifier: anInteger ifAbsent: aBlock
	^ [ (Object _objectForOop: anInteger)
		ifNil: aBlock
		ifNotNil:[ :object | (SystemRepository _oopIsDead: anInteger)
							ifTrue: aBlock
							ifFalse: [ object ] ] 
		] on: Error do: [:e | 
			"oop fishing in GemStone may return internal objects that do not implement ifNil:ifNotNil:.
			_oopIsDead can also error (see method comment). 
			capture these objects here and return nil"
			aBlock value ]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gemtalksystems.com/mailman/archives/gemstone-smalltalk/attachments/20220722/2768d6e2/attachment.htm>


More information about the GemStone-Smalltalk mailing list