[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