[Vm-dev] latest changes (no idea from when it started) are making FFI win32 crash (and FFI Callbacks are not reliable anymore either)

Esteban Lorenzano estebanlm at gmail.com
Tue Nov 29 10:54:39 UTC 2016


Hi,

So, I’m building the PharoVM along with all his dependencies. For me, this is a major step because I can drop the old build process finally. 
Now, I’m having serious problems with FFI (that they were not present before), : 


1. CRASH IN WINDOWS (32bits):

In Win32, it crashes automatically when trying to access this funtion:

getEnvSize: nameString
	^ self ffiCall: #( int GetEnvironmentVariableA ( String nameString, nil, 0 ) ) module: #Kernel32

 (this works perfectly fine in older versions)

2. CALLBACKS FAILING: 

Callbacks have problems. The examples passes but they are very simple… as soon as I try to do something complicates (like unqlite bindings or libgit2 bindings, who use callbacks intensively), callbacks stops working. 
I traced the problem up to this method: 

StackInterpreter>>#returnAs:ThroughCallback:Context:

returnAs: returnTypeOop ThroughCallback: vmCallbackContext Context: callbackMethodContext
	"callbackMethodContext is an activation of invokeCallback:[stack:registers:jmpbuf:].
	 Its sender is the VM's state prior to the callback.  Reestablish that state (via longjmp),
	 and mark callbackMethodContext as dead."
	<export: true>
	<var: #vmCallbackContext type: #'VMCallbackContext *'>
	| calloutMethodContext theFP thePage |
	<var: #theFP type: #'char *'>
	<var: #thePage type: #'StackPage *'>
	((self isIntegerObject: returnTypeOop)
	 and: [self isLiveContext: callbackMethodContext]) ifFalse:
		[^false].
	calloutMethodContext := self externalInstVar: SenderIndex ofContext: callbackMethodContext.
	(self isLiveContext: calloutMethodContext) ifFalse:
		[^false].
	"We're about to leave this stack page; must save the current frame's instructionPointer."
	self push: instructionPointer.
	self externalWriteBackHeadFramePointers.
	"Mark callbackMethodContext as dead; the common case is that it is the current frame.
	 We go the extra mile for the debugger."
	(self isSingleContext: callbackMethodContext)
		ifTrue: [self markContextAsDead: callbackMethodContext]
		ifFalse:
			[theFP := self frameOfMarriedContext: callbackMethodContext.
			 framePointer = theFP "common case"
				ifTrue:
					[(self isBaseFrame: theFP)
						ifTrue: [stackPages freeStackPage: stackPage]
						ifFalse: "calloutMethodContext is immediately below on the same page.  Make it current."
							[instructionPointer := (self frameCallerSavedIP: framePointer) asUnsignedInteger.
							 stackPointer := framePointer + (self frameStackedReceiverOffset: framePointer) + objectMemory wordSize.
							 framePointer := self frameCallerFP: framePointer.
							 self setMethod: (self frameMethodObject: framePointer).
							 self restoreCStackStateForCallbackContext: vmCallbackContext.
							 "N.B. siglongjmp is defines as _longjmp on non-win32 platforms.
							  This matches the use of _setjmp in ia32abicc.c."
							 self siglong: vmCallbackContext trampoline jmp: (self integerValueOf: returnTypeOop).
							 ^true]]
				ifFalse:
					[self externalDivorceFrame: theFP andContext: callbackMethodContext.
					 self markContextAsDead: callbackMethodContext]].
	"Make the calloutMethodContext the active frame.  The case where calloutMethodContext
	 is immediately below callbackMethodContext on the same page is handled above."
	(self isStillMarriedContext: calloutMethodContext)
		ifTrue:
			[theFP := self frameOfMarriedContext: calloutMethodContext.
			 thePage := stackPages stackPageFor: theFP.
			 "findSPOf:on: points to the word beneath the instructionPointer, but
			  there is no instructionPointer on the top frame of the current page."
			 self assert: thePage ~= stackPage.
			 stackPointer := (self findSPOf: theFP on: thePage) - objectMemory wordSize.
			 framePointer := theFP]
		ifFalse:
			[thePage := self makeBaseFrameFor: calloutMethodContext.
			 framePointer := thePage headFP.
			 stackPointer := thePage headSP].
	instructionPointer := self popStack.
	self setMethod: (objectMemory fetchPointer: MethodIndex ofObject: calloutMethodContext).
	self setStackPageAndLimit: thePage.
	self restoreCStackStateForCallbackContext: vmCallbackContext.
	 "N.B. siglongjmp is defines as _longjmp on non-win32 platforms.
	  This matches the use of _setjmp in ia32abicc.c."
	self siglong: vmCallbackContext trampoline jmp: (self integerValueOf: returnTypeOop).
	"NOTREACHED"
	^true

with the first siglongjmp callbacks are passing fine. 
with the last (it would be if  framePointer = theFP AND !(isBaseFrame: theFP) ) it doesn’t. 

So… from here I’m a bit lost… I need some help :)

thanks,
Esteban





More information about the Vm-dev mailing list