[squeak-dev] XTHash fails to find libcrypto in Linux / Altitude only on Win32?

mkobetic at gmail.com mkobetic at gmail.com
Fri Jul 27 03:04:11 UTC 2012


I'd love to have a better answer, but this is the joy of relying on third party delivered external libraries. The Xtreams code is looking for library 'libcrypto.so' (without any version numbers attached). On some systems it will be found on others it won't. The quickest test at the smalltalk level is

	XTLibCrypto versionString

If it returns a version string the library is found fine. If not then you get the module not found error. The best way to see what's available at the OS level is running something like:

	ldconfig -p | grep libcrypto

If it shows one that's called just 'libcrypto.so' and it is the right architecture (libc6) vs (libc6, x86-64) then it should work. If you have a system which only sees libs with the version numbers then you need to create an "unversioned" symlink somewhere in the loader path (LD_LIBRARY_PATH). What I usually do is add a file to /etc/ld.so.conf.d/ that lists directories where I maintain my own symlinks.

Alternatively, you can probably modify the Smalltalk code to reference the version number as well, but that can be cumbersome. The difficulty with that approach is that the version number changes inconveniently often. These days you can easily encounter 0.9.7, 0.9.8, or one of the 1.0.0 flavors and 1.1.0 is coming out soon. Moreover the Xtreams code will work with any of those (the newer versions may provide more algorithms or capabilities, but that's not available in the squeak port yet).

It's been a while since I played with these in Squeak/Pharo, but I also had difficulties with various Squeak/Pharo and VM combinations that I didn't have time to narrow down. So sometimes trying different VMs showed different results too. Unfortunately I don't have anything more specific than that.

In VW we've recently implemented a more flexible mechanism for the selection of the implementation back-end which allows falling back to other implementations if the preferred one fails (e.g. a plain smalltalk implementation, or in Squeak it could be a plugin based one). The streams really don't care how the algorithm is actually implemented as long as the XTHash and XTHMAC APIs are functioning (BTW, XTHMAC is a keyed-hash construct not something specific to Macs). This sort of mechanism can provide a bit more user friendly experience, although it can hide the fact that you're falling back to something else when that may not be what you want. Pick your poison :-).

HTH,

Martin

"Chris Cunnington"<smalltalktelevision at gmail.com> wrote:
> I deployed Altitude in CentOS and it produced a debug log, which I've 
> attached below. Altitude needs SHA hashes and asks Xtreams for them. 
> Works in Mac. Seems to fail in CentOS.
> 
> XTHash makes an OS choice. If it's not Win32, then it uses 
> XTLibCryptoHash. That works on Mac. On Linux it throws #externalCallFailed.
> 
> So, the Linux class - XTLibCrytpoHash - fails on Linux, but works on 
> Mac. The Mac class - XTHMAC - isn't used at all.
> 
> Suspecting I may be wrong, and feeling limited by looking only at a 
> command line, I downloaded Virtualbox, loaded CentOS 5.3, Squeak, and 
> Altitude.
> 
> I updated to the latest Squeak build - #12145 and ran the tests for 
> Xtreams-XtrasTests. That package contains XTHMACTest and XTHashTest. All 
> six tests failed.
> 
> They try to find libcrypto, which seems ready to be found at:
> 
> /usr/lib/.libcrypto.so.1.0.0.hmac
> /usr/lib/.libcrypto.so.10.hmac
> /usr/lib/libcrypto.so.1.0.0
> /usr/lib/libcypto.so.10
> 
> 
> I'm going to venture to say that people who use Xtreams in Squeak are 
> more likely to deploy it on Win32 than Linux. Does anybody use Xtreams 
> in Squeak and deploy on Linux?
> 
> Thanks,
> Chris
> 
> 
> 
> 
> Error: External module not found
> 25 July 2012 2:25:32.041 pm
> 
> VM: unix - Smalltalk
> Image: Squeak4.4-alpha [latest update: #12144]
> 
> SecurityManager state:
> Restricted: false
> FileAccess: true
> SocketAccess: true
> Working Dir /home/squeakmap
> Trusted Dir /home/squeakmap/secure
> Untrusted Dir /home/squeakmap/My Squeak
> 
> XTLibCryptoHash(Object)>>error:
>      Receiver: a XTLibCryptoHash
>      Arguments and temporary variables:
> <<error during printing>
>      Receiver's instance variables:
>          library:     nil
>          context:     a XTEVPMDCTX
>          algorithm:     nil
> 
> XTLibCryptoHash(Object)>>externalCallFailed
>      Receiver: a XTLibCryptoHash
>      Arguments and temporary variables:
>          errCode:     15
>      Receiver's instance variables:
>          library:     nil
>          context:     a XTEVPMDCTX
>          algorithm:     nil
> 
> XTLibCryptoHash>>EVP_MD_CTX_init:
>      Receiver: a XTLibCryptoHash
>      Arguments and temporary variables:
>          ctx:     a XTEVPMDCTX
>      Receiver's instance variables:
>          library:     nil
>          context:     a XTEVPMDCTX
>          algorithm:     nil
> 
> XTLibCryptoHash>>initialize
>      Receiver: a XTLibCryptoHash
>      Arguments and temporary variables:
> 
>      Receiver's instance variables:
>          library:     nil
>          context:     a XTEVPMDCTX
>          algorithm:     nil
> 
> XTHash class>>new
>      Receiver: XTHash
>      Arguments and temporary variables:
> 
>      Receiver's instance variables:
>          superclass:     Object
>          methodDict:     a 
> MethodDictionary(#algorithm:->(XTHash>>#algorithm: "a CompiledMet...etc...
>          format:     2
>          instanceVariables:     nil
>          organization:     ('initialize-release' algorithm: release reset)
> ('accessing' bloc...etc...
>          subclasses:     {XTBCryptHash . XTHMAC . XTLibCryptoHash}
>          name:     #XTHash
>          classPool:     nil
>          sharedPools:     nil
>          environment:     Smalltalk globals "a SystemDictionary with 
> lots of globals"
>          category:     #'Xtreams-Xtras'
> 
> XTDigestWriteStream>>algorithm:
>      Receiver: XTDigestWriteStream
> XTNullWriteStream
> nil
>      Arguments and temporary variables:
>          id:     'sha1'
>      Receiver's instance variables:
>          destination:     XTNullWriteStream
> nil
>          input:     #[62 111 100 121 101 32 123 102 111 110 116 45 115 
> 105 122 101 58 32 51 ...etc...
>          digest:     nil
>          hash:     nil
> 
> XTNullWriteStream(XTWriteStream)>>hashing:
>      Receiver: XTNullWriteStream
> nil
>      Arguments and temporary variables:
>          id:     'sha1'
>      Receiver's instance variables:
>          destination:     nil
> 
> ALArchive>>digest
>      Receiver: an ALArchive
>      Arguments and temporary variables:
>          stream:     nil
>      Receiver's instance variables:
>          bytes:     #[252 253 249 14 65 76 72 116 109 108 82 101 115 111 
> 117 114 99 101 1 1 ...etc...
>          external:     #()
> 
> ALDigestLocator>>keyForResource:
>      Receiver: an ALDigestLocator
>      Arguments and temporary variables:
>          aResource:     an ALHtmlResource
>      Receiver's instance variables:
>          paths:     a 
> Dictionary('3~tHvS3DJ2hB3~7Cg54M3eZW3LU'->/3~tHvS3DJ2hB3~7Cg54M3eZW3LU...etc...
>          resources:     a Dictionary(/->an ALHtmlResource 
> /3~tHvS3DJ2hB3~7Cg54M3eZW3LU->an A...etc...
> 
> ALDigestLocator(ALLocator)>>pathForResource:
>      Receiver: an ALDigestLocator
>      Arguments and temporary variables:
>          aResource:     an ALHtmlResource
>          key:     nil
>      Receiver's instance variables:
>          paths:     a 
> Dictionary('3~tHvS3DJ2hB3~7Cg54M3eZW3LU'->/3~tHvS3DJ2hB3~7Cg54M3eZW3LU...etc...
>          resources:     a Dictionary(/->an ALHtmlResource 
> /3~tHvS3DJ2hB3~7Cg54M3eZW3LU->an A...etc...
> 
> ALRenderingContext>>registerNavigation:
>      Receiver: an ALRenderingContext
>      Arguments and temporary variables:
>          aValuable:     [closure] in ALCounterComponent>>renderContentOn:
>          callback:     an ALCallbackResource
>      Receiver's instance variables:
>          locator:     an ALDigestLocator
>          resource:     an ALHtmlResource
> 
> ALAppATag>>navigate:
>      Receiver: an ALAppATag
>      Arguments and temporary variables:
>          aValuable:     [closure] in ALCounterComponent>>renderContentOn:
>          path:     nil
>      Receiver's instance variables:
>          canvas:     an ALAppHtml5Canvas
>          attributes:     an OrderedCollection()
> 
> ALCounterComponent>>renderContentOn:
>      Receiver: an ALCounterComponent
>      Arguments and temporary variables:
>          html:     an ALAppHtml5Canvas
>      Receiver's instance variables:
>          counter:     0
> 
> [] in [] in ALCounterComponent>>renderOn:
>      Receiver: an ALCounterComponent
>      Arguments and temporary variables:
>          html:     an ALAppHtml5Canvas
>      Receiver's instance variables:
>          counter:     0
> 
> BlockClosure>>cull:
>      Receiver: [closure] in [] in ALCounterComponent>>renderOn:
>      Arguments and temporary variables:
> <<error during printing>
>      Receiver's instance variables:
>          outerContext:     [] in ALCounterComponent>>renderOn:
>          startpc:     74
>          numArgs:     0
> 
> ALAppHtml5Canvas(ALCanvas)>>renderBlock:
>      Receiver: an ALAppHtml5Canvas
>      Arguments and temporary variables:
>          aBlock:     [closure] in [] in ALCounterComponent>>renderOn:
>      Receiver's instance variables:
>          stream:     XTEncodeWriteStream
> XTChunkingWriteStream
> XTPositionWriteSubstream
> XTEx...etc...
>          stack:     an OrderedCollection(an ALHtmlTag an ALBodyTag)
>          current:     an ALAppATag
>          context:     an ALRenderingContext
>          form:     nil
> 
> BlockClosure>>renderOn:
>      Receiver: [closure] in [] in ALCounterComponent>>renderOn:
>      Arguments and temporary variables:
>          aCanvas:     an ALAppHtml5Canvas
>      Receiver's instance variables:
>          outerContext:     [] in ALCounterComponent>>renderOn:
>          startpc:     74
>          numArgs:     0
> 
> ALAppHtml5Canvas(ALCanvas)>>render:
>      Receiver: an ALAppHtml5Canvas
>      Arguments and temporary variables:
>          anObject:     [closure] in [] in ALCounterComponent>>renderOn:
>      Receiver's instance variables:
>          stream:     XTEncodeWriteStream
> XTChunkingWriteStream
> XTPositionWriteSubstream
> XTEx...etc...
>          stack:     an OrderedCollection(an ALHtmlTag an ALBodyTag)
>          current:     an ALAppATag
>          context:     an ALRenderingContext
>          form:     nil
> 
> [] in ALBodyTag(ALBrush)>>with:
>      Receiver: an ALBodyTag
>      Arguments and temporary variables:
>          anObject:     [closure] in [] in ALCounterComponent>>renderOn:
>      Receiver's instance variables:
>          canvas:     an ALAppHtml5Canvas
>          attributes:     an OrderedCollection()
> 
> 
> --- The full stack ---
> XTLibCryptoHash(Object)>>error:
> XTLibCryptoHash(Object)>>externalCallFailed
> XTLibCryptoHash>>EVP_MD_CTX_init:
> XTLibCryptoHash>>initialize
> XTHash class>>new
> XTDigestWriteStream>>algorithm:
> XTNullWriteStream(XTWriteStream)>>hashing:
> ALArchive>>digest
> ALDigestLocator>>keyForResource:
> ALDigestLocator(ALLocator)>>pathForResource:
> ALRenderingContext>>registerNavigation:
> ALAppATag>>navigate:
> ALCounterComponent>>renderContentOn:
> [] in [] in ALCounterComponent>>renderOn:
> BlockClosure>>cull:
> ALAppHtml5Canvas(ALCanvas)>>renderBlock:
> BlockClosure>>renderOn:
> ALAppHtml5Canvas(ALCanvas)>>render:
> [] in ALBodyTag(ALBrush)>>with:
>   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> BlockClosure>>ensure:
> ALBodyTag(ALBrush)>>with:
> ALAppHtml5Canvas(ALHtml5Canvas)>>body:
> [] in ALCounterComponent>>renderOn:
> BlockClosure>>cull:
> ALAppHtml5Canvas(ALCanvas)>>renderBlock:
> BlockClosure>>renderOn:
> ALAppHtml5Canvas(ALCanvas)>>render:
> [] in ALHtmlTag(ALBrush)>>with:
> BlockClosure>>ensure:
> ALHtmlTag(ALBrush)>>with:
> ALAppHtml5Canvas(ALHtml5Canvas)>>html:
> ALCounterComponent>>renderOn:
> ALHtmlResource>>renderOnStream:locator:
> [] in ALHtmlResource>>handleGet:locator:
> [] in ALEntity>>writeBodyInto:
> BlockClosure>>ensure:
> ALEntity>>writeBodyInto:
> ALTerminalRelay>>write:into:
> ALEntity(ALMimeMessage)>>writeInto:
> ALResponse(ALHttpMessage)>>writeBodyInto:
> ALTerminalRelay>>write:into:
> ALResponse(ALMimeMessage)>>writeInto:
> ALConnection>>handleRequest
> ALConnection>>loop
> [] in [] in ALConnection>>run
> BlockClosure>>on:do:
> [] in ALConnection>>run
> BlockClosure>>ifCurtailed:
> ALConnection>>run
> [] in ALConnection>>start
> [] in BlockClosure>>newProcess
> 



More information about the Squeak-dev mailing list